Commit 2954bf5c authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

heap: Move HeapHashTableBacking support into its own file

Same as with HeapVectorBacking, move the GC support for
HeapHashTableBacking into its own file instead of distributing it over
the GC internals.

Bug: 1056170
Change-Id: Ie4d26fd4135258c5cf4f4a133e7084d8105e02fc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2074617
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: default avatarOmer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#744742}
parent 1bb2aa7a
......@@ -46,6 +46,7 @@ blink_platform_sources("heap") {
"blink_gc_memory_dump_provider.h",
"cancelable_task_scheduler.cc",
"cancelable_task_scheduler.h",
"collection_support/heap_hash_table_backing.h",
"collection_support/heap_vector_backing.h",
"disallow_new_wrapper.h",
"finalizer_traits.h",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_HASH_TABLE_BACKING_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_HASH_TABLE_BACKING_H_
#include "third_party/blink/renderer/platform/heap/heap_page.h"
#include "third_party/blink/renderer/platform/heap/threading_traits.h"
#include "third_party/blink/renderer/platform/heap/trace_traits.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
template <typename Table>
class HeapHashTableBacking {
DISALLOW_NEW();
IS_GARBAGE_COLLECTED_TYPE();
public:
template <typename Backing>
static void* AllocateObject(size_t size);
static void Finalize(void* pointer);
void FinalizeGarbageCollectedObject() { Finalize(this); }
};
template <typename Table>
struct ThreadingTrait<HeapHashTableBacking<Table>> {
STATIC_ONLY(ThreadingTrait);
using Key = typename Table::KeyType;
using Value = typename Table::ValueType;
static const ThreadAffinity kAffinity =
(ThreadingTrait<Key>::kAffinity == kMainThreadOnly) &&
(ThreadingTrait<Value>::kAffinity == kMainThreadOnly)
? kMainThreadOnly
: kAnyThread;
};
// static
template <typename Table>
template <typename Backing>
void* HeapHashTableBacking<Table>::AllocateObject(size_t size) {
ThreadState* state =
ThreadStateFor<ThreadingTrait<Backing>::kAffinity>::GetState();
DCHECK(state->IsAllocationAllowed());
const char* type_name = WTF_HEAP_PROFILER_TYPE_NAME(Backing);
return state->Heap().AllocateOnArenaIndex(
state, size, BlinkGC::kHashTableArenaIndex, GCInfoTrait<Backing>::Index(),
type_name);
}
template <typename Table>
void HeapHashTableBacking<Table>::Finalize(void* pointer) {
using Value = typename Table::ValueType;
static_assert(
!std::is_trivially_destructible<Value>::value,
"Finalization of trivially destructible classes should not happen.");
HeapObjectHeader* header = HeapObjectHeader::FromPayload(pointer);
// Use the payload size as recorded by the heap to determine how many
// elements to finalize.
size_t length = header->PayloadSize() / sizeof(Value);
Value* table = reinterpret_cast<Value*>(pointer);
for (unsigned i = 0; i < length; ++i) {
if (!Table::IsEmptyOrDeletedBucket(table[i]))
table[i].~Value();
}
}
template <typename Table>
struct MakeGarbageCollectedTrait<HeapHashTableBacking<Table>> {
static HeapHashTableBacking<Table>* Call(size_t num_elements) {
CHECK_GT(num_elements, 0u);
void* memory = HeapHashTableBacking<Table>::template AllocateObject<
HeapHashTableBacking<Table>>(num_elements *
sizeof(typename Table::ValueType));
HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
// Placement new as regular operator new() is deleted.
HeapHashTableBacking<Table>* object =
::new (memory) HeapHashTableBacking<Table>();
header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>();
return object;
}
};
template <typename Table>
struct FinalizerTrait<HeapHashTableBacking<Table>> {
STATIC_ONLY(FinalizerTrait);
static const bool kNonTrivialFinalizer =
!std::is_trivially_destructible<typename Table::ValueType>::value;
static void Finalize(void* obj) {
internal::FinalizerTraitImpl<HeapHashTableBacking<Table>,
kNonTrivialFinalizer>::Finalize(obj);
}
};
// The trace trait for the heap hashtable backing is used when we find a
// direct pointer to the backing from the conservative stack scanner. This
// normally indicates that there is an ongoing iteration over the table, and so
// we disable weak processing of table entries. When the backing is found
// through the owning hash table we mark differently, in order to do weak
// processing.
template <typename Table>
struct TraceTrait<HeapHashTableBacking<Table>> {
STATIC_ONLY(TraceTrait);
using Backing = HeapHashTableBacking<Table>;
using ValueType = typename Table::ValueTraits::TraitType;
using Traits = typename Table::ValueTraits;
public:
static TraceDescriptor GetTraceDescriptor(void* self) {
return {self, Trace<WTF::kNoWeakHandling>};
}
static TraceDescriptor GetWeakTraceDescriptor(void* self) {
return GetWeakTraceDescriptorImpl<ValueType>::GetWeakTraceDescriptor(self);
}
template <WTF::WeakHandlingFlag WeakHandling = WTF::kNoWeakHandling>
static void Trace(Visitor* visitor, void* self) {
if (visitor->ConcurrentTracingBailOut({self, &Trace}))
return;
static_assert(WTF::IsTraceableInCollectionTrait<Traits>::value ||
WTF::IsWeak<ValueType>::value,
"T should not be traced");
WTF::TraceInCollectionTrait<WeakHandling, Backing, void>::Trace(visitor,
self);
}
private:
template <typename ValueType>
struct GetWeakTraceDescriptorImpl {
static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
return {backing, nullptr};
}
};
template <typename K, typename V>
struct GetWeakTraceDescriptorImpl<WTF::KeyValuePair<K, V>> {
static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
return GetWeakTraceDescriptorKVPImpl<K, V>::GetWeakTraceDescriptor(
backing);
}
template <typename KeyType,
typename ValueType,
bool ephemeron_semantics = (WTF::IsWeak<KeyType>::value &&
!WTF::IsWeak<ValueType>::value &&
WTF::IsTraceable<ValueType>::value) ||
(WTF::IsWeak<ValueType>::value &&
!WTF::IsWeak<KeyType>::value &&
WTF::IsTraceable<KeyType>::value)>
struct GetWeakTraceDescriptorKVPImpl {
static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
return {backing, nullptr};
}
};
template <typename KeyType, typename ValueType>
struct GetWeakTraceDescriptorKVPImpl<KeyType, ValueType, true> {
static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
return {backing, Trace<WTF::kWeakHandling>};
}
};
};
};
} // namespace blink
namespace WTF {
// This trace method is for tracing a HashTableBacking either through regular
// tracing (via the relevant TraceTraits) or when finding a HashTableBacking
// through conservative stack scanning (which will treat all references in the
// backing strongly).
template <WTF::WeakHandlingFlag WeakHandling, typename Table>
struct TraceHashTableBackingInCollectionTrait {
using Value = typename Table::ValueType;
using Traits = typename Table::ValueTraits;
static bool Trace(blink::Visitor* visitor, void* self) {
static_assert(IsTraceableInCollectionTrait<Traits>::value ||
WTF::IsWeak<Value>::value,
"Table should not be traced");
Value* array = reinterpret_cast<Value*>(self);
blink::HeapObjectHeader* header =
blink::HeapObjectHeader::FromPayload(self);
// Use the payload size as recorded by the heap to determine how many
// elements to trace.
size_t length = header->PayloadSize() / sizeof(Value);
const bool is_concurrent = visitor->IsConcurrent();
for (size_t i = 0; i < length; ++i) {
// If tracing concurrently, use a concurrent-safe version of
// IsEmptyOrDeletedBucket (check performed on a local copy instead
// of directly on the bucket).
if (is_concurrent) {
if (!HashTableHelper<Value, typename Table::ExtractorType,
typename Table::KeyTraitsType>::
IsEmptyOrDeletedBucketSafe(array[i])) {
blink::TraceCollectionIfEnabled<WeakHandling, Value, Traits>::Trace(
visitor, &array[i]);
}
} else {
if (!HashTableHelper<Value, typename Table::ExtractorType,
typename Table::KeyTraitsType>::
IsEmptyOrDeletedBucket(array[i])) {
blink::TraceCollectionIfEnabled<WeakHandling, Value, Traits>::Trace(
visitor, &array[i]);
}
}
}
return false;
}
};
template <typename Table>
struct TraceInCollectionTrait<kNoWeakHandling,
blink::HeapHashTableBacking<Table>,
void> {
static bool Trace(blink::Visitor* visitor, void* self) {
return TraceHashTableBackingInCollectionTrait<kNoWeakHandling,
Table>::Trace(visitor, self);
}
};
template <typename Table>
struct TraceInCollectionTrait<kWeakHandling,
blink::HeapHashTableBacking<Table>,
void> {
static bool Trace(blink::Visitor* visitor, void* self) {
return TraceHashTableBackingInCollectionTrait<kWeakHandling, Table>::Trace(
visitor, self);
}
};
// Key value pairs, as used in HashMap. To disambiguate template choice we have
// to have two versions, first the one with no special weak handling, then the
// one with weak handling.
template <typename Key, typename Value, typename Traits>
struct TraceInCollectionTrait<kNoWeakHandling,
KeyValuePair<Key, Value>,
Traits> {
using EphemeronHelper =
blink::EphemeronKeyValuePair<Key,
Value,
typename Traits::KeyTraits,
typename Traits::ValueTraits>;
static bool Trace(blink::Visitor* visitor, KeyValuePair<Key, Value>& self) {
if (WTF::IsWeak<Key>::value != WTF::IsWeak<Value>::value) {
// Strongification of Weak/Strong and Strong/Weak.
EphemeronHelper helper(&self.key, &self.value);
visitor->VisitEphemeronKeyValuePair(
helper.key, helper.value,
blink::TraceCollectionIfEnabled<
kNoWeakHandling, typename EphemeronHelper::KeyType,
typename EphemeronHelper::KeyTraits>::Trace,
blink::TraceCollectionIfEnabled<
kNoWeakHandling, typename EphemeronHelper::ValueType,
typename EphemeronHelper::ValueTraits>::Trace);
} else {
// Strongification of Strong/Strong or Weak/Weak. Order does not matter
// here.
blink::TraceCollectionIfEnabled<
kNoWeakHandling, Key, typename Traits::KeyTraits>::Trace(visitor,
&self.key);
blink::TraceCollectionIfEnabled<
kNoWeakHandling, Value,
typename Traits::ValueTraits>::Trace(visitor, &self.value);
}
return false;
}
};
template <typename Key, typename Value, typename Traits>
struct TraceInCollectionTrait<kWeakHandling, KeyValuePair<Key, Value>, Traits> {
using EphemeronHelper =
blink::EphemeronKeyValuePair<Key,
Value,
typename Traits::KeyTraits,
typename Traits::ValueTraits>;
static bool IsAlive(KeyValuePair<Key, Value>& self) {
// Needed for Weak/Weak, Strong/Weak (reverse ephemeron), and Weak/Strong
// (ephemeron). Order of invocation does not matter as tracing weak key or
// value does not have any side effects.
return blink::TraceCollectionIfEnabled<
WeakHandlingTrait<Key>::value, Key,
typename Traits::KeyTraits>::IsAlive(self.key) &&
blink::TraceCollectionIfEnabled<
WeakHandlingTrait<Value>::value, Value,
typename Traits::ValueTraits>::IsAlive(self.value);
}
static bool Trace(blink::Visitor* visitor, KeyValuePair<Key, Value>& self) {
EphemeronHelper helper(&self.key, &self.value);
return visitor->VisitEphemeronKeyValuePair(
helper.key, helper.value,
blink::TraceCollectionIfEnabled<
WeakHandlingTrait<typename EphemeronHelper::KeyType>::value,
typename EphemeronHelper::KeyType,
typename EphemeronHelper::KeyTraits>::Trace,
blink::TraceCollectionIfEnabled<
WeakHandlingTrait<typename EphemeronHelper::ValueType>::value,
typename EphemeronHelper::ValueType,
typename EphemeronHelper::ValueTraits>::Trace);
}
};
} // namespace WTF
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_HASH_TABLE_BACKING_H_
......@@ -91,8 +91,6 @@ struct FinalizerTrait {
};
class HeapAllocator;
template <typename Table>
class HeapHashTableBacking;
template <typename T, typename U, typename V>
struct FinalizerTrait<LinkedHashSet<T, U, V, HeapAllocator>> {
......@@ -137,17 +135,6 @@ struct FinalizerTrait<Deque<T, inlineCapacity, HeapAllocator>> {
}
};
template <typename Table>
struct FinalizerTrait<HeapHashTableBacking<Table>> {
STATIC_ONLY(FinalizerTrait);
static const bool kNonTrivialFinalizer =
!std::is_trivially_destructible<typename Table::ValueType>::value;
static void Finalize(void* obj) {
internal::FinalizerTraitImpl<HeapHashTableBacking<Table>,
kNonTrivialFinalizer>::Finalize(obj);
}
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_FINALIZER_TRAITS_H_
......@@ -8,6 +8,7 @@
#include <type_traits>
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h"
#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector_backing.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/heap_buildflags.h"
......@@ -46,16 +47,6 @@ template <typename T>
struct IsAllowedInContainer<T, typename T::IsDisallowedInContainerMarker>
: std::false_type {};
template <typename Table>
class HeapHashTableBacking {
DISALLOW_NEW();
IS_GARBAGE_COLLECTED_TYPE();
public:
static void Finalize(void* pointer);
void FinalizeGarbageCollectedObject() { Finalize(this); }
};
// This is a static-only class used as a trait on collections to make them heap
// allocated. However see also HeapListHashSetAllocator.
class PLATFORM_EXPORT HeapAllocator {
......@@ -90,16 +81,9 @@ class PLATFORM_EXPORT HeapAllocator {
template <typename T, typename HashTable>
static T* AllocateHashTableBacking(size_t size) {
uint32_t gc_info_index =
GCInfoTrait<HeapHashTableBacking<HashTable>>::Index();
ThreadState* state =
ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
const char* type_name =
WTF_HEAP_PROFILER_TYPE_NAME(HeapHashTableBacking<HashTable>);
return reinterpret_cast<T*>(
MarkAsConstructed(state->Heap().AllocateOnArenaIndex(
state, size, BlinkGC::kHashTableArenaIndex, gc_info_index,
type_name)));
MakeGarbageCollected<HeapHashTableBacking<HashTable>>(
size / sizeof(typename HashTable::ValueType)));
}
template <typename T, typename HashTable>
static T* AllocateZeroedHashTableBacking(size_t size) {
......@@ -396,23 +380,6 @@ class HeapListHashSetAllocator : public HeapAllocator {
}
};
template <typename Table>
void HeapHashTableBacking<Table>::Finalize(void* pointer) {
using Value = typename Table::ValueType;
static_assert(
!std::is_trivially_destructible<Value>::value,
"Finalization of trivially destructible classes should not happen.");
HeapObjectHeader* header = HeapObjectHeader::FromPayload(pointer);
// Use the payload size as recorded by the heap to determine how many
// elements to finalize.
size_t length = header->PayloadSize() / sizeof(Value);
Value* table = reinterpret_cast<Value*>(pointer);
for (unsigned i = 0; i < length; ++i) {
if (!Table::IsEmptyOrDeletedBucket(table[i]))
table[i].~Value();
}
}
namespace internal {
template <typename T>
......
......@@ -56,8 +56,6 @@ struct DefaultThreadingTrait<T, true> {
};
class HeapAllocator;
template <typename Table>
class HeapHashTableBacking;
template <typename T>
class Member;
template <typename T>
......@@ -128,18 +126,6 @@ struct ThreadingTrait<HashCountedSet<T, U, V, HeapAllocator>> {
static const ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity;
};
template <typename Table>
struct ThreadingTrait<HeapHashTableBacking<Table>> {
STATIC_ONLY(ThreadingTrait);
using Key = typename Table::KeyType;
using Value = typename Table::ValueType;
static const ThreadAffinity kAffinity =
(ThreadingTrait<Key>::Affinity == kMainThreadOnly) &&
(ThreadingTrait<Value>::Affinity == kMainThreadOnly)
? kMainThreadOnly
: kAnyThread;
};
template <typename T, typename U, typename V, typename W, typename X>
class HeapHashMap;
template <typename T, typename U, typename V>
......
......@@ -21,6 +21,8 @@
namespace blink {
template <typename Table>
class HeapHashTableBacking;
template <typename ValueArg, wtf_size_t inlineCapacity>
class HeapListHashSetAllocator;
template <typename T>
......@@ -172,78 +174,6 @@ void TraceTrait<T>::Trace(Visitor* visitor, void* self) {
static_cast<T*>(self)->Trace(visitor);
}
// The trace trait for the heap hashtable backing is used when we find a
// direct pointer to the backing from the conservative stack scanner. This
// normally indicates that there is an ongoing iteration over the table, and so
// we disable weak processing of table entries. When the backing is found
// through the owning hash table we mark differently, in order to do weak
// processing.
template <typename Table>
struct TraceTrait<HeapHashTableBacking<Table>> {
STATIC_ONLY(TraceTrait);
using Backing = HeapHashTableBacking<Table>;
using ValueType = typename Table::ValueTraits::TraitType;
using Traits = typename Table::ValueTraits;
public:
static TraceDescriptor GetTraceDescriptor(void* self) {
return {self, Trace<WTF::kNoWeakHandling>};
}
static TraceDescriptor GetWeakTraceDescriptor(void* self) {
return GetWeakTraceDescriptorImpl<ValueType>::GetWeakTraceDescriptor(self);
}
template <WTF::WeakHandlingFlag WeakHandling = WTF::kNoWeakHandling>
static void Trace(Visitor* visitor, void* self) {
if (visitor->ConcurrentTracingBailOut({self, &Trace}))
return;
static_assert(WTF::IsTraceableInCollectionTrait<Traits>::value ||
WTF::IsWeak<ValueType>::value,
"T should not be traced");
WTF::TraceInCollectionTrait<WeakHandling, Backing, void>::Trace(visitor,
self);
}
private:
template <typename ValueType>
struct GetWeakTraceDescriptorImpl {
static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
return {backing, nullptr};
}
};
template <typename K, typename V>
struct GetWeakTraceDescriptorImpl<WTF::KeyValuePair<K, V>> {
static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
return GetWeakTraceDescriptorKVPImpl<K, V>::GetWeakTraceDescriptor(
backing);
}
template <typename KeyType,
typename ValueType,
bool ephemeron_semantics = (WTF::IsWeak<KeyType>::value &&
!WTF::IsWeak<ValueType>::value &&
WTF::IsTraceable<ValueType>::value) ||
(WTF::IsWeak<ValueType>::value &&
!WTF::IsWeak<KeyType>::value &&
WTF::IsTraceable<KeyType>::value)>
struct GetWeakTraceDescriptorKVPImpl {
static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
return {backing, nullptr};
}
};
template <typename KeyType, typename ValueType>
struct GetWeakTraceDescriptorKVPImpl<KeyType, ValueType, true> {
static TraceDescriptor GetWeakTraceDescriptor(void* backing) {
return {backing, Trace<WTF::kWeakHandling>};
}
};
};
};
// This trace trait for std::pair will null weak members if their referent is
// collected. If you have a collection that contain weakness it does not remove
// entries from the collection that contain nulled weak members.
......@@ -376,68 +306,6 @@ struct TraceInCollectionTrait<kWeakHandling, blink::WeakMember<T>, Traits> {
}
};
// This trace method is for tracing a HashTableBacking either through regular
// tracing (via the relevant TraceTraits) or when finding a HashTableBacking
// through conservative stack scanning (which will treat all references in the
// backing strongly).
template <WTF::WeakHandlingFlag WeakHandling, typename Table>
struct TraceHashTableBackingInCollectionTrait {
using Value = typename Table::ValueType;
using Traits = typename Table::ValueTraits;
static bool Trace(blink::Visitor* visitor, void* self) {
static_assert(IsTraceableInCollectionTrait<Traits>::value ||
WTF::IsWeak<Value>::value,
"Table should not be traced");
Value* array = reinterpret_cast<Value*>(self);
blink::HeapObjectHeader* header =
blink::HeapObjectHeader::FromPayload(self);
// Use the payload size as recorded by the heap to determine how many
// elements to trace.
size_t length = header->PayloadSize() / sizeof(Value);
const bool is_concurrent = visitor->IsConcurrent();
for (size_t i = 0; i < length; ++i) {
// If tracing concurrently, use a concurrent-safe version of
// IsEmptyOrDeletedBucket (check performed on a local copy instead
// of directly on the bucket).
if (is_concurrent) {
if (!HashTableHelper<Value, typename Table::ExtractorType,
typename Table::KeyTraitsType>::
IsEmptyOrDeletedBucketSafe(array[i])) {
blink::TraceCollectionIfEnabled<WeakHandling, Value, Traits>::Trace(
visitor, &array[i]);
}
} else {
if (!HashTableHelper<Value, typename Table::ExtractorType,
typename Table::KeyTraitsType>::
IsEmptyOrDeletedBucket(array[i])) {
blink::TraceCollectionIfEnabled<WeakHandling, Value, Traits>::Trace(
visitor, &array[i]);
}
}
}
return false;
}
};
template <typename Table>
struct TraceInCollectionTrait<kNoWeakHandling,
blink::HeapHashTableBacking<Table>,
void> {
static bool Trace(blink::Visitor* visitor, void* self) {
return TraceHashTableBackingInCollectionTrait<kNoWeakHandling,
Table>::Trace(visitor, self);
}
};
template <typename Table>
struct TraceInCollectionTrait<kWeakHandling,
blink::HeapHashTableBacking<Table>,
void> {
static bool Trace(blink::Visitor* visitor, void* self) {
return TraceHashTableBackingInCollectionTrait<kWeakHandling, Table>::Trace(
visitor, self);
}
};
// This specialization of TraceInCollectionTrait is for the backing of
// HeapListHashSet. This is for the case that we find a reference to the
// backing from the stack. That probably means we have a GC while we are in a
......@@ -494,80 +362,6 @@ struct TraceInCollectionTrait<
}
};
// Key value pairs, as used in HashMap. To disambiguate template choice we have
// to have two versions, first the one with no special weak handling, then the
// one with weak handling.
template <typename Key, typename Value, typename Traits>
struct TraceInCollectionTrait<kNoWeakHandling,
KeyValuePair<Key, Value>,
Traits> {
using EphemeronHelper =
blink::EphemeronKeyValuePair<Key,
Value,
typename Traits::KeyTraits,
typename Traits::ValueTraits>;
static bool Trace(blink::Visitor* visitor, KeyValuePair<Key, Value>& self) {
if (WTF::IsWeak<Key>::value != WTF::IsWeak<Value>::value) {
// Strongification of Weak/Strong and Strong/Weak.
EphemeronHelper helper(&self.key, &self.value);
visitor->VisitEphemeronKeyValuePair(
helper.key, helper.value,
blink::TraceCollectionIfEnabled<
kNoWeakHandling, typename EphemeronHelper::KeyType,
typename EphemeronHelper::KeyTraits>::Trace,
blink::TraceCollectionIfEnabled<
kNoWeakHandling, typename EphemeronHelper::ValueType,
typename EphemeronHelper::ValueTraits>::Trace);
} else {
// Strongification of Strong/Strong or Weak/Weak. Order does not matter
// here.
blink::TraceCollectionIfEnabled<
kNoWeakHandling, Key, typename Traits::KeyTraits>::Trace(visitor,
&self.key);
blink::TraceCollectionIfEnabled<
kNoWeakHandling, Value,
typename Traits::ValueTraits>::Trace(visitor, &self.value);
}
return false;
}
};
template <typename Key, typename Value, typename Traits>
struct TraceInCollectionTrait<kWeakHandling, KeyValuePair<Key, Value>, Traits> {
using EphemeronHelper =
blink::EphemeronKeyValuePair<Key,
Value,
typename Traits::KeyTraits,
typename Traits::ValueTraits>;
static bool IsAlive(KeyValuePair<Key, Value>& self) {
// Needed for Weak/Weak, Strong/Weak (reverse ephemeron), and Weak/Strong
// (ephemeron). Order of invocation does not matter as tracing weak key or
// value does not have any side effects.
return blink::TraceCollectionIfEnabled<
WeakHandlingTrait<Key>::value, Key,
typename Traits::KeyTraits>::IsAlive(self.key) &&
blink::TraceCollectionIfEnabled<
WeakHandlingTrait<Value>::value, Value,
typename Traits::ValueTraits>::IsAlive(self.value);
}
static bool Trace(blink::Visitor* visitor, KeyValuePair<Key, Value>& self) {
EphemeronHelper helper(&self.key, &self.value);
return visitor->VisitEphemeronKeyValuePair(
helper.key, helper.value,
blink::TraceCollectionIfEnabled<
WeakHandlingTrait<typename EphemeronHelper::KeyType>::value,
typename EphemeronHelper::KeyType,
typename EphemeronHelper::KeyTraits>::Trace,
blink::TraceCollectionIfEnabled<
WeakHandlingTrait<typename EphemeronHelper::ValueType>::value,
typename EphemeronHelper::ValueType,
typename EphemeronHelper::ValueTraits>::Trace);
}
};
// Nodes used by LinkedHashSet. Again we need two versions to disambiguate the
// template.
template <typename Value, typename Traits>
......
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