Commit 0d6df47e authored by Michael Lippautz's avatar Michael Lippautz Committed by Chromium LUCI CQ

heap: Forbid inheriting from more containers

Inheriting from Heap* containers is dangerous because of missing
virtual destructors and trace methods.

This only leaves HeapHashSet as container that can be inherited from,
which has one actual use in production code.

Bug: 1056170
Change-Id: I66a301754adb4d970ccc631f1113edcb915c3abc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2589855Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836765}
parent 1bc83f66
...@@ -183,7 +183,7 @@ template <typename KeyArg, ...@@ -183,7 +183,7 @@ template <typename KeyArg,
typename HashArg = typename DefaultHash<KeyArg>::Hash, typename HashArg = typename DefaultHash<KeyArg>::Hash,
typename KeyTraitsArg = HashTraits<KeyArg>, typename KeyTraitsArg = HashTraits<KeyArg>,
typename MappedTraitsArg = HashTraits<MappedArg>> typename MappedTraitsArg = HashTraits<MappedArg>>
class HeapHashMap : public HashMap<KeyArg, class HeapHashMap final : public HashMap<KeyArg,
MappedArg, MappedArg,
HashArg, HashArg,
KeyTraitsArg, KeyTraitsArg,
...@@ -262,7 +262,7 @@ struct GCInfoTrait<HeapHashSet<T, U, V>> ...@@ -262,7 +262,7 @@ struct GCInfoTrait<HeapHashSet<T, U, V>>
template <typename Value, template <typename Value,
typename HashFunctions = typename DefaultHash<Value>::Hash, typename HashFunctions = typename DefaultHash<Value>::Hash,
typename Traits = HashTraits<Value>> typename Traits = HashTraits<Value>>
class HeapHashCountedSet class HeapHashCountedSet final
: public HashCountedSet<Value, HashFunctions, Traits, HeapAllocator> { : public HashCountedSet<Value, HashFunctions, Traits, HeapAllocator> {
IS_GARBAGE_COLLECTED_CONTAINER_TYPE(); IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
DISALLOW_NEW(); DISALLOW_NEW();
...@@ -292,7 +292,7 @@ struct GCInfoTrait<HeapHashCountedSet<T, U, V>> ...@@ -292,7 +292,7 @@ struct GCInfoTrait<HeapHashCountedSet<T, U, V>>
: public GCInfoTrait<HashCountedSet<T, U, V, HeapAllocator>> {}; : public GCInfoTrait<HashCountedSet<T, U, V, HeapAllocator>> {};
template <typename T, wtf_size_t inlineCapacity = 0> template <typename T, wtf_size_t inlineCapacity = 0>
class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> { class HeapVector final : public Vector<T, inlineCapacity, HeapAllocator> {
IS_GARBAGE_COLLECTED_CONTAINER_TYPE(); IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
DISALLOW_NEW(); DISALLOW_NEW();
...@@ -369,7 +369,7 @@ struct GCInfoTrait<HeapVector<T, inlineCapacity>> ...@@ -369,7 +369,7 @@ struct GCInfoTrait<HeapVector<T, inlineCapacity>>
: public GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator>> {}; : public GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator>> {};
template <typename T> template <typename T>
class HeapDeque : public Deque<T, 0, HeapAllocator> { class HeapDeque final : public Deque<T, 0, HeapAllocator> {
IS_GARBAGE_COLLECTED_CONTAINER_TYPE(); IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
DISALLOW_NEW(); DISALLOW_NEW();
......
...@@ -38,6 +38,15 @@ class CollectionWrapper : public GarbageCollected<CollectionWrapper<T>> { ...@@ -38,6 +38,15 @@ class CollectionWrapper : public GarbageCollected<CollectionWrapper<T>> {
template <typename T> template <typename T>
struct MethodAdapterBase { struct MethodAdapterBase {
template <typename U>
static void insert(T& t, U&& u) {
t.insert(std::forward<U>(u));
}
static void erase(T& t, typename T::iterator&& it) {
t.erase(std::forward<typename T::iterator>(it));
}
static void Swap(T& a, T& b) { a.swap(b); } static void Swap(T& a, T& b) { a.swap(b); }
}; };
...@@ -56,7 +65,8 @@ void AddToCollection() { ...@@ -56,7 +65,8 @@ void AddToCollection() {
driver.SingleConcurrentStep(); driver.SingleConcurrentStep();
for (int j = 0; j < kIterations; ++j) { for (int j = 0; j < kIterations; ++j) {
int num = kIterations * i + j; int num = kIterations * i + j;
collection->insert(MakeGarbageCollected<IntegerObject>(num)); MethodAdapter<C>::insert(*collection,
MakeGarbageCollected<IntegerObject>(num));
} }
} }
driver.FinishSteps(); driver.FinishSteps();
...@@ -71,13 +81,14 @@ void RemoveFromCollectionAtLocation(GetLocation location) { ...@@ -71,13 +81,14 @@ void RemoveFromCollectionAtLocation(GetLocation location) {
MakeGarbageCollected<CollectionWrapper<C>>(); MakeGarbageCollected<CollectionWrapper<C>>();
C* collection = persistent->GetCollection(); C* collection = persistent->GetCollection();
for (int i = 0; i < (kIterations * kIterations); ++i) { for (int i = 0; i < (kIterations * kIterations); ++i) {
collection->insert(MakeGarbageCollected<IntegerObject>(i)); MethodAdapter<C>::insert(*collection,
MakeGarbageCollected<IntegerObject>(i));
} }
driver.Start(); driver.Start();
for (int i = 0; i < kIterations; ++i) { for (int i = 0; i < kIterations; ++i) {
driver.SingleConcurrentStep(); driver.SingleConcurrentStep();
for (int j = 0; j < kIterations; ++j) { for (int j = 0; j < kIterations; ++j) {
collection->erase(location(collection)); MethodAdapter<C>::erase(*collection, location(collection));
} }
} }
driver.FinishSteps(); driver.FinishSteps();
...@@ -121,7 +132,8 @@ void ClearCollection() { ...@@ -121,7 +132,8 @@ void ClearCollection() {
for (int i = 0; i < kIterations; ++i) { for (int i = 0; i < kIterations; ++i) {
driver.SingleConcurrentStep(); driver.SingleConcurrentStep();
for (int j = 0; j < kIterations; ++j) { for (int j = 0; j < kIterations; ++j) {
collection->insert(MakeGarbageCollected<IntegerObject>(i)); MethodAdapter<C>::insert(*collection,
MakeGarbageCollected<IntegerObject>(i));
} }
collection->clear(); collection->clear();
} }
...@@ -140,7 +152,8 @@ void SwapCollections() { ...@@ -140,7 +152,8 @@ void SwapCollections() {
for (int i = 0; i < (kIterations * kIterations); ++i) { for (int i = 0; i < (kIterations * kIterations); ++i) {
C* new_collection = MakeGarbageCollected<C>(); C* new_collection = MakeGarbageCollected<C>();
for (int j = 0; j < kIterations * i; ++j) { for (int j = 0; j < kIterations * i; ++j) {
new_collection->insert(MakeGarbageCollected<IntegerObject>(j)); MethodAdapter<C>::insert(*new_collection,
MakeGarbageCollected<IntegerObject>(j));
} }
driver.SingleConcurrentStep(); driver.SingleConcurrentStep();
MethodAdapter<C>::Swap(*collection, *new_collection); MethodAdapter<C>::Swap(*collection, *new_collection);
...@@ -152,31 +165,34 @@ void SwapCollections() { ...@@ -152,31 +165,34 @@ void SwapCollections() {
// HeapHashMap // HeapHashMap
template <typename T> template <typename T>
class HeapHashMapAdapter : public HeapHashMap<T, T> { using IdentityHashMap = HeapHashMap<T, T>;
public:
template <typename T>
struct MethodAdapter<HeapHashMap<T, T>>
: public MethodAdapterBase<HeapHashMap<T, T>> {
template <typename U> template <typename U>
ALWAYS_INLINE void insert(U* u) { static void insert(HeapHashMap<T, T>& map, U&& u) {
HeapHashMap<T, T>::insert(u, u); map.insert(u, u);
} }
}; };
TEST_F(ConcurrentMarkingTest, AddToHashMap) { TEST_F(ConcurrentMarkingTest, AddToHashMap) {
AddToCollection<HeapHashMapAdapter<Member<IntegerObject>>>(); AddToCollection<IdentityHashMap<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfHashMap) { TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfHashMap) {
RemoveFromBeginningOfCollection<HeapHashMapAdapter<Member<IntegerObject>>>(); RemoveFromBeginningOfCollection<IdentityHashMap<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfHashMap) { TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfHashMap) {
RemoveFromMiddleOfCollection<HeapHashMapAdapter<Member<IntegerObject>>>(); RemoveFromMiddleOfCollection<IdentityHashMap<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromEndOfHashMap) { TEST_F(ConcurrentMarkingTest, RemoveFromEndOfHashMap) {
RemoveFromEndOfCollection<HeapHashMapAdapter<Member<IntegerObject>>>(); RemoveFromEndOfCollection<IdentityHashMap<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, ClearHashMap) { TEST_F(ConcurrentMarkingTest, ClearHashMap) {
ClearCollection<HeapHashMapAdapter<Member<IntegerObject>>>(); ClearCollection<IdentityHashMap<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, SwapHashMap) { TEST_F(ConcurrentMarkingTest, SwapHashMap) {
SwapCollections<HeapHashMapAdapter<Member<IntegerObject>>>(); SwapCollections<IdentityHashMap<Member<IntegerObject>>>();
} }
// HeapHashSet // HeapHashSet
...@@ -286,7 +302,7 @@ void PopFromCollection() { ...@@ -286,7 +302,7 @@ void PopFromCollection() {
MakeGarbageCollected<CollectionWrapper<V>>(); MakeGarbageCollected<CollectionWrapper<V>>();
V* vector = persistent->GetCollection(); V* vector = persistent->GetCollection();
for (int i = 0; i < (kIterations * kIterations); ++i) { for (int i = 0; i < (kIterations * kIterations); ++i) {
vector->insert(MakeGarbageCollected<IntegerObject>(i)); MethodAdapter<V>::insert(*vector, MakeGarbageCollected<IntegerObject>(i));
} }
driver.Start(); driver.Start();
for (int i = 0; i < kIterations; ++i) { for (int i = 0; i < kIterations; ++i) {
...@@ -314,142 +330,140 @@ void PopFromCollection() { ...@@ -314,142 +330,140 @@ void PopFromCollection() {
TEST_F(ConcurrentMarkingTest, Swap##name) { SwapCollections<type>(); } \ TEST_F(ConcurrentMarkingTest, Swap##name) { SwapCollections<type>(); } \
TEST_F(ConcurrentMarkingTest, PopFrom##name) { PopFromCollection<type>(); } TEST_F(ConcurrentMarkingTest, PopFrom##name) { PopFromCollection<type>(); }
template <typename T, wtf_size_t inlineCapacity = 0> template <typename T, wtf_size_t inlineCapacity>
class HeapVectorAdapter : public HeapVector<T, inlineCapacity> { struct MethodAdapter<HeapVector<T, inlineCapacity>>
using Base = HeapVector<T, inlineCapacity>; : public MethodAdapterBase<HeapVector<T, inlineCapacity>> {
public:
template <typename U> template <typename U>
ALWAYS_INLINE void insert(U* u) { static void insert(HeapVector<T, inlineCapacity>& vector, U&& u) {
Base::push_back(u); vector.push_back(std::forward<U>(u));
} }
}; };
TEST_F(ConcurrentMarkingTest, AddToVector) { TEST_F(ConcurrentMarkingTest, AddToVector) {
AddToCollection<HeapVectorAdapter<Member<IntegerObject>>>(); AddToCollection<HeapVector<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfVector) { TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfVector) {
RemoveFromBeginningOfCollection<HeapVectorAdapter<Member<IntegerObject>>>(); RemoveFromBeginningOfCollection<HeapVector<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfVector) { TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfVector) {
RemoveFromMiddleOfCollection<HeapVectorAdapter<Member<IntegerObject>>>(); RemoveFromMiddleOfCollection<HeapVector<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromEndOfVector) { TEST_F(ConcurrentMarkingTest, RemoveFromEndOfVector) {
RemoveFromEndOfCollection<HeapVectorAdapter<Member<IntegerObject>>>(); RemoveFromEndOfCollection<HeapVector<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, ClearVector) { TEST_F(ConcurrentMarkingTest, ClearVector) {
ClearCollection<HeapVectorAdapter<Member<IntegerObject>>>(); ClearCollection<HeapVector<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, SwapVector) { TEST_F(ConcurrentMarkingTest, SwapVector) {
SwapCollections<HeapVectorAdapter<Member<IntegerObject>>>(); SwapCollections<HeapVector<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, PopFromVector) { TEST_F(ConcurrentMarkingTest, PopFromVector) {
PopFromCollection<HeapVectorAdapter<Member<IntegerObject>>>(); PopFromCollection<HeapVector<Member<IntegerObject>>>();
} }
// HeapVector with inlined buffer // HeapVector with inlined buffer
template <typename T> template <typename T>
class HeapInlinedVectorAdapter : public HeapVectorAdapter<T, 10> {}; using HeapVectorWithInlineStorage = HeapVector<T, 10>;
TEST_F(ConcurrentMarkingTest, AddToInlinedVector) { TEST_F(ConcurrentMarkingTest, AddToInlinedVector) {
AddToCollection<HeapInlinedVectorAdapter<Member<IntegerObject>>>(); AddToCollection<HeapVectorWithInlineStorage<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfInlinedVector) { TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfInlinedVector) {
RemoveFromBeginningOfCollection< RemoveFromBeginningOfCollection<
HeapInlinedVectorAdapter<Member<IntegerObject>>>(); HeapVectorWithInlineStorage<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfInlinedVector) { TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfInlinedVector) {
RemoveFromMiddleOfCollection< RemoveFromMiddleOfCollection<
HeapInlinedVectorAdapter<Member<IntegerObject>>>(); HeapVectorWithInlineStorage<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromEndOfInlinedVector) { TEST_F(ConcurrentMarkingTest, RemoveFromEndOfInlinedVector) {
RemoveFromEndOfCollection<HeapInlinedVectorAdapter<Member<IntegerObject>>>(); RemoveFromEndOfCollection<
HeapVectorWithInlineStorage<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, ClearInlinedVector) { TEST_F(ConcurrentMarkingTest, ClearInlinedVector) {
ClearCollection<HeapInlinedVectorAdapter<Member<IntegerObject>>>(); ClearCollection<HeapVectorWithInlineStorage<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, SwapInlinedVector) { TEST_F(ConcurrentMarkingTest, SwapInlinedVector) {
SwapCollections<HeapInlinedVectorAdapter<Member<IntegerObject>>>(); SwapCollections<HeapVectorWithInlineStorage<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, PopFromInlinedVector) { TEST_F(ConcurrentMarkingTest, PopFromInlinedVector) {
PopFromCollection<HeapInlinedVectorAdapter<Member<IntegerObject>>>(); PopFromCollection<HeapVectorWithInlineStorage<Member<IntegerObject>>>();
} }
// HeapVector of std::pairs // HeapVector of std::pairs
template <typename T> template <typename T>
class HeapVectorOfPairsAdapter : public HeapVector<std::pair<T, T>> { using HeapVectorOfPairs = HeapVector<std::pair<T, T>>;
using Base = HeapVector<std::pair<T, T>>;
public: template <typename T, wtf_size_t inlineCapacity>
struct MethodAdapter<HeapVector<std::pair<T, T>, inlineCapacity>>
: public MethodAdapterBase<HeapVector<std::pair<T, T>, inlineCapacity>> {
template <typename U> template <typename U>
ALWAYS_INLINE void insert(U* u) { static void insert(HeapVector<std::pair<T, T>, inlineCapacity>& vector,
Base::push_back(std::make_pair<T, T>(u, u)); U&& u) {
vector.push_back(std::make_pair<U&, U&>(u, u));
} }
}; };
TEST_F(ConcurrentMarkingTest, AddToVectorOfPairs) { TEST_F(ConcurrentMarkingTest, AddToVectorOfPairs) {
AddToCollection<HeapVectorOfPairsAdapter<Member<IntegerObject>>>(); AddToCollection<HeapVectorOfPairs<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfVectorOfPairs) { TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfVectorOfPairs) {
RemoveFromBeginningOfCollection< RemoveFromBeginningOfCollection<HeapVectorOfPairs<Member<IntegerObject>>>();
HeapVectorOfPairsAdapter<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfVectorOfPairs) { TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfVectorOfPairs) {
RemoveFromMiddleOfCollection< RemoveFromMiddleOfCollection<HeapVectorOfPairs<Member<IntegerObject>>>();
HeapVectorOfPairsAdapter<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromEndOfVectorOfPairs) { TEST_F(ConcurrentMarkingTest, RemoveFromEndOfVectorOfPairs) {
RemoveFromEndOfCollection<HeapVectorOfPairsAdapter<Member<IntegerObject>>>(); RemoveFromEndOfCollection<HeapVectorOfPairs<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, ClearVectorOfPairs) { TEST_F(ConcurrentMarkingTest, ClearVectorOfPairs) {
ClearCollection<HeapVectorOfPairsAdapter<Member<IntegerObject>>>(); ClearCollection<HeapVectorOfPairs<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, SwapVectorOfPairs) { TEST_F(ConcurrentMarkingTest, SwapVectorOfPairs) {
SwapCollections<HeapVectorOfPairsAdapter<Member<IntegerObject>>>(); SwapCollections<HeapVectorOfPairs<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, PopFromVectorOfPairs) { TEST_F(ConcurrentMarkingTest, PopFromVectorOfPairs) {
PopFromCollection<HeapVectorOfPairsAdapter<Member<IntegerObject>>>(); PopFromCollection<HeapVectorOfPairs<Member<IntegerObject>>>();
} }
// HeapDeque // HeapDeque
template <typename T> template <typename T>
class HeapDequeAdapter : public HeapDeque<T> { struct MethodAdapter<HeapDeque<T>> : public MethodAdapterBase<HeapDeque<T>> {
public:
template <typename U> template <typename U>
ALWAYS_INLINE void insert(U* u) { static void insert(HeapDeque<T>& deque, U&& u) {
HeapDeque<T>::push_back(u); deque.push_back(std::forward<U>(u));
}
ALWAYS_INLINE void erase(typename HeapDeque<T>::iterator) {
HeapDeque<T>::pop_back();
} }
ALWAYS_INLINE void swap(HeapDequeAdapter<T>& other) {
HeapDeque<T>::Swap(other); static void erase(HeapDeque<T>& deque, typename HeapDeque<T>::iterator&& it) {
deque.pop_back();
} }
static void Swap(HeapDeque<T>& a, HeapDeque<T>& b) { a.Swap(b); }
}; };
TEST_F(ConcurrentMarkingTest, AddToDeque) { TEST_F(ConcurrentMarkingTest, AddToDeque) {
AddToCollection<HeapDequeAdapter<Member<IntegerObject>>>(); AddToCollection<HeapDeque<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfDeque) { TEST_F(ConcurrentMarkingTest, RemoveFromBeginningOfDeque) {
RemoveFromBeginningOfCollection<HeapDequeAdapter<Member<IntegerObject>>>(); RemoveFromBeginningOfCollection<HeapDeque<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfDeque) { TEST_F(ConcurrentMarkingTest, RemoveFromMiddleOfDeque) {
RemoveFromMiddleOfCollection<HeapDequeAdapter<Member<IntegerObject>>>(); RemoveFromMiddleOfCollection<HeapDeque<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, RemoveFromEndOfDeque) { TEST_F(ConcurrentMarkingTest, RemoveFromEndOfDeque) {
RemoveFromEndOfCollection<HeapDequeAdapter<Member<IntegerObject>>>(); RemoveFromEndOfCollection<HeapDeque<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, ClearDeque) { TEST_F(ConcurrentMarkingTest, ClearDeque) {
ClearCollection<HeapDequeAdapter<Member<IntegerObject>>>(); ClearCollection<HeapDeque<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, SwapDeque) { TEST_F(ConcurrentMarkingTest, SwapDeque) {
SwapCollections<HeapDequeAdapter<Member<IntegerObject>>>(); SwapCollections<HeapDeque<Member<IntegerObject>>>();
} }
TEST_F(ConcurrentMarkingTest, PopFromDeque) { TEST_F(ConcurrentMarkingTest, PopFromDeque) {
PopFromCollection<HeapDequeAdapter<Member<IntegerObject>>>(); PopFromCollection<HeapDeque<Member<IntegerObject>>>();
} }
namespace { namespace {
......
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