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

heap: Using atomics in list_hash_set only when garbage collected

Adding an Allocator template parameter to ListHashSetNodeBasePointer
so that atomic writes/reads are only used when the collection is
garbage collection.

This is an optimization to reduce performance regressions (see Bug).

Bug: 1040437
Change-Id: I76f69614071bb023b2879c600533cffd0f60a75a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1995175Reviewed-by: default avatarMichael Lippautz <mlippautz@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#730228}
parent 1d7ae876
...@@ -58,7 +58,7 @@ class ListHashSetReverseIterator; ...@@ -58,7 +58,7 @@ class ListHashSetReverseIterator;
template <typename Set> template <typename Set>
class ListHashSetConstReverseIterator; class ListHashSetConstReverseIterator;
template <typename ValueArg> template <typename ValueArg, typename Allocator>
class ListHashSetNodeBase; class ListHashSetNodeBase;
template <typename ValueArg, typename Allocator> template <typename ValueArg, typename Allocator>
class ListHashSetNode; class ListHashSetNode;
...@@ -272,9 +272,9 @@ class ListHashSet ...@@ -272,9 +272,9 @@ class ListHashSet
typename Allocator::AllocatorProvider allocator_provider_; typename Allocator::AllocatorProvider allocator_provider_;
}; };
template <typename T> template <typename T, typename Allocator>
class ListHashSetNodeBasePointer { class ListHashSetNodeBasePointer {
using NodeType = ListHashSetNodeBase<T>; using NodeType = ListHashSetNodeBase<T, Allocator>;
public: public:
ListHashSetNodeBasePointer& operator=( ListHashSetNodeBasePointer& operator=(
...@@ -285,7 +285,7 @@ class ListHashSetNodeBasePointer { ...@@ -285,7 +285,7 @@ class ListHashSetNodeBasePointer {
template <typename U> template <typename U>
ListHashSetNodeBasePointer& operator=( ListHashSetNodeBasePointer& operator=(
const ListHashSetNodeBasePointer<U>& other) { const ListHashSetNodeBasePointer<U, Allocator>& other) {
SetSafe(other); SetSafe(other);
return *this; return *this;
} }
...@@ -308,12 +308,23 @@ class ListHashSetNodeBasePointer { ...@@ -308,12 +308,23 @@ class ListHashSetNodeBasePointer {
NodeType& operator*() const { return *Get(); } NodeType& operator*() const { return *Get(); }
private: private:
template <bool = Allocator::kIsGarbageCollected>
void SetSafe(NodeType* node) { void SetSafe(NodeType* node) {
return AsAtomicPtr(&node_)->store(node, std::memory_order_relaxed); AsAtomicPtr(&node_)->store(node, std::memory_order_relaxed);
}
template <>
void SetSafe<false>(NodeType* node) {
node_ = node;
} }
template <bool = Allocator::kIsGarbageCollected>
NodeType* GetSafe() const { NodeType* GetSafe() const {
return AsAtomicPtr(&node_)->load(std::memory_order_relaxed); return AsAtomicPtr(&node_)->load(std::memory_order_relaxed);
} }
template <>
NodeType* GetSafe<false>() const {
return node_;
}
NodeType* node_ = nullptr; NodeType* node_ = nullptr;
...@@ -324,7 +335,7 @@ class ListHashSetNodeBasePointer { ...@@ -324,7 +335,7 @@ class ListHashSetNodeBasePointer {
// ListHashSetNode has this base class to hold the members because the MSVC // ListHashSetNode has this base class to hold the members because the MSVC
// compiler otherwise gets into circular template dependencies when trying to do // compiler otherwise gets into circular template dependencies when trying to do
// sizeof on a node. // sizeof on a node.
template <typename ValueArg> template <typename ValueArg, typename Allocator>
class ListHashSetNodeBase { class ListHashSetNodeBase {
DISALLOW_NEW(); DISALLOW_NEW();
...@@ -334,8 +345,8 @@ class ListHashSetNodeBase { ...@@ -334,8 +345,8 @@ class ListHashSetNodeBase {
public: public:
ValueArg value_; ValueArg value_;
ListHashSetNodeBasePointer<ValueArg> prev_; ListHashSetNodeBasePointer<ValueArg, Allocator> prev_;
ListHashSetNodeBasePointer<ValueArg> next_; ListHashSetNodeBasePointer<ValueArg, Allocator> next_;
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
bool is_allocated_ = true; bool is_allocated_ = true;
#endif #endif
...@@ -346,7 +357,7 @@ template <typename ValueArg, size_t inlineCapacity> ...@@ -346,7 +357,7 @@ template <typename ValueArg, size_t inlineCapacity>
struct ListHashSetAllocator : public PartitionAllocator { struct ListHashSetAllocator : public PartitionAllocator {
typedef PartitionAllocator TableAllocator; typedef PartitionAllocator TableAllocator;
typedef ListHashSetNode<ValueArg, ListHashSetAllocator> Node; typedef ListHashSetNode<ValueArg, ListHashSetAllocator> Node;
typedef ListHashSetNodeBase<ValueArg> NodeBase; typedef ListHashSetNodeBase<ValueArg, ListHashSetAllocator> NodeBase;
class AllocatorProvider { class AllocatorProvider {
DISALLOW_NEW(); DISALLOW_NEW();
...@@ -451,19 +462,19 @@ struct ListHashSetAllocator : public PartitionAllocator { ...@@ -451,19 +462,19 @@ struct ListHashSetAllocator : public PartitionAllocator {
}; };
template <typename ValueArg, typename AllocatorArg> template <typename ValueArg, typename AllocatorArg>
class ListHashSetNode : public ListHashSetNodeBase<ValueArg> { class ListHashSetNode : public ListHashSetNodeBase<ValueArg, AllocatorArg> {
public: public:
typedef AllocatorArg NodeAllocator; typedef AllocatorArg NodeAllocator;
typedef ValueArg Value; typedef ValueArg Value;
template <typename U> template <typename U>
ListHashSetNode(U&& value) ListHashSetNode(U&& value)
: ListHashSetNodeBase<ValueArg>(std::forward<U>(value)) {} : ListHashSetNodeBase<ValueArg, AllocatorArg>(std::forward<U>(value)) {}
void* operator new(size_t, NodeAllocator* allocator) { void* operator new(size_t, NodeAllocator* allocator) {
static_assert( static_assert(sizeof(ListHashSetNode) ==
sizeof(ListHashSetNode) == sizeof(ListHashSetNodeBase<ValueArg>), sizeof(ListHashSetNodeBase<ValueArg, AllocatorArg>),
"please add any fields to the base"); "please add any fields to the base");
return allocator->AllocateNode(); return allocator->AllocateNode();
} }
......
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