| // Copyright 2021 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/trace_traits.h" |
| #include "third_party/blink/renderer/platform/wtf/buildflags.h" |
| |
| #if BUILDFLAG(USE_V8_OILPAN) |
| #include "third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_hash_table_backing.h" |
| #else // !USE_V8_OILPAN |
| #include "third_party/blink/renderer/platform/heap/impl/collection_support/heap_hash_table_backing.h" |
| #endif // !USE_V8_OILPAN |
| |
| namespace blink { |
| |
| // Helper for processing ephemerons represented as KeyValuePair. Reorders |
| // parameters if needed so that KeyType is always weak. |
| template <typename _KeyType, |
| typename _ValueType, |
| typename _KeyTraits, |
| typename _ValueTraits, |
| bool = WTF::IsWeak<_ValueType>::value> |
| struct EphemeronKeyValuePair { |
| using KeyType = _KeyType; |
| using ValueType = _ValueType; |
| using KeyTraits = _KeyTraits; |
| using ValueTraits = _ValueTraits; |
| |
| // Ephemerons have different weakness for KeyType and ValueType. If weakness |
| // is equal, we either have Strong/Strong, or Weak/Weak, which would indicate |
| // a full strong or fully weak pair. |
| static constexpr bool is_ephemeron = |
| WTF::IsWeak<KeyType>::value != WTF::IsWeak<ValueType>::value; |
| |
| static_assert(!WTF::IsWeak<KeyType>::value || |
| WTF::IsWeakMemberType<KeyType>::value, |
| "Weakness must be encoded using WeakMember."); |
| |
| EphemeronKeyValuePair(const KeyType* k, const ValueType* v) |
| : key(k), value(v) {} |
| const KeyType* key; |
| const ValueType* value; |
| }; |
| |
| template <typename _KeyType, |
| typename _ValueType, |
| typename _KeyTraits, |
| typename _ValueTraits> |
| struct EphemeronKeyValuePair<_KeyType, |
| _ValueType, |
| _KeyTraits, |
| _ValueTraits, |
| true> : EphemeronKeyValuePair<_ValueType, |
| _KeyType, |
| _ValueTraits, |
| _KeyTraits, |
| false> { |
| EphemeronKeyValuePair(const _KeyType* k, const _ValueType* v) |
| : EphemeronKeyValuePair<_ValueType, |
| _KeyType, |
| _ValueTraits, |
| _KeyTraits, |
| false>(v, k) {} |
| }; |
| |
| } // namespace blink |
| |
| namespace WTF { |
| |
| template <typename Table> |
| struct TraceInCollectionTrait<kNoWeakHandling, |
| blink::HeapHashTableBacking<Table>, |
| void> { |
| static void Trace(blink::Visitor* visitor, const void* self) { |
| TraceHashTableBackingInCollectionTrait<kNoWeakHandling, Table>::Trace( |
| visitor, self); |
| } |
| }; |
| |
| template <typename Table> |
| struct TraceInCollectionTrait<kWeakHandling, |
| blink::HeapHashTableBacking<Table>, |
| void> { |
| static void Trace(blink::Visitor* visitor, const void* self) { |
| TraceHashTableBackingInCollectionTrait<kWeakHandling, Table>::Trace(visitor, |
| self); |
| } |
| }; |
| |
| // 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 Key, |
| typename Value, |
| typename Traits> |
| struct TraceKeyValuePairInCollectionTrait { |
| using EphemeronHelper = |
| blink::EphemeronKeyValuePair<Key, |
| Value, |
| typename Traits::KeyTraits, |
| typename Traits::ValueTraits>; |
| |
| static void Trace(blink::Visitor* visitor, |
| const Key* key, |
| const Value* value) { |
| TraceImpl::Trace(visitor, key, value); |
| } |
| |
| private: |
| struct TraceImplEphemerons { |
| // Strongification of ephemerons, i.e., Weak/Strong and Strong/Weak. |
| static void Trace(blink::Visitor* visitor, |
| const Key* key, |
| const Value* value) { |
| // Strongification of ephemerons, i.e., Weak/Strong and Strong/Weak. |
| // The helper ensures that helper.key always refers to the weak part and |
| // helper.value always refers to the dependent part. |
| // We distinguish ephemeron from Weak/Weak and Strong/Strong to allow |
| // users to override visitation behavior. An example is creating a heap |
| // snapshot, where it is useful to annotate values as being kept alive |
| // from keys rather than the table. |
| EphemeronHelper helper(key, value); |
| if (WeakHandling == kNoWeakHandling) { |
| // Strongify the weak part. |
| blink::TraceCollectionIfEnabled< |
| kNoWeakHandling, typename EphemeronHelper::KeyType, |
| typename EphemeronHelper::KeyTraits>::Trace(visitor, helper.key); |
| } |
| // The following passes on kNoWeakHandling for tracing value as the value |
| // callback is only invoked to keep value alive iff key is alive, |
| // following ephemeron semantics. |
| visitor->TraceEphemeron(*helper.key, helper.value); |
| } |
| }; |
| |
| struct TraceImplDefault { |
| static void Trace(blink::Visitor* visitor, |
| const Key* key, |
| const Value* value) { |
| // Strongification of non-ephemeron KVP, i.e., Strong/Strong or Weak/Weak. |
| // Order does not matter here. |
| blink::TraceCollectionIfEnabled< |
| kNoWeakHandling, Key, typename Traits::KeyTraits>::Trace(visitor, |
| key); |
| blink::TraceCollectionIfEnabled< |
| kNoWeakHandling, Value, typename Traits::ValueTraits>::Trace(visitor, |
| value); |
| } |
| }; |
| |
| using TraceImpl = typename std::conditional< |
| EphemeronHelper::is_ephemeron && |
| WTF::IsTraceable<typename EphemeronHelper::ValueType>::value, |
| TraceImplEphemerons, |
| TraceImplDefault>::type; |
| }; |
| |
| // Trait for strong treatment of KeyValuePair. This is used to handle regular |
| // KVP but also for strongification of otherwise weakly handled KVPs. |
| template <typename Key, typename Value, typename Traits> |
| struct TraceInCollectionTrait<kNoWeakHandling, |
| KeyValuePair<Key, Value>, |
| Traits> { |
| static void Trace(blink::Visitor* visitor, |
| const KeyValuePair<Key, Value>& self) { |
| TraceKeyValuePairInCollectionTrait<kNoWeakHandling, Key, Value, |
| Traits>::Trace(visitor, &self.key, |
| &self.value); |
| } |
| }; |
| |
| template <typename Key, typename Value, typename Traits> |
| struct TraceInCollectionTrait<kWeakHandling, KeyValuePair<Key, Value>, Traits> { |
| static bool IsAlive(const blink::LivenessBroker& info, |
| const 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(info, self.key) && |
| blink::TraceCollectionIfEnabled< |
| WeakHandlingTrait<Value>::value, Value, |
| typename Traits::ValueTraits>::IsAlive(info, self.value); |
| } |
| |
| static void Trace(blink::Visitor* visitor, |
| const KeyValuePair<Key, Value>& self) { |
| TraceKeyValuePairInCollectionTrait<kWeakHandling, Key, Value, |
| Traits>::Trace(visitor, &self.key, |
| &self.value); |
| } |
| }; |
| |
| template <typename Key, typename Value, typename Traits> |
| struct TraceInCollectionTrait< |
| kNoWeakHandling, |
| internal::ConcurrentBucket<KeyValuePair<Key, Value>>, |
| Traits> { |
| static void Trace( |
| blink::Visitor* visitor, |
| const internal::ConcurrentBucket<KeyValuePair<Key, Value>>& self) { |
| TraceKeyValuePairInCollectionTrait<kNoWeakHandling, Key, Value, |
| Traits>::Trace(visitor, self.key(), |
| self.value()); |
| } |
| }; |
| |
| template <typename Key, typename Value, typename Traits> |
| struct TraceInCollectionTrait< |
| kWeakHandling, |
| internal::ConcurrentBucket<KeyValuePair<Key, Value>>, |
| Traits> { |
| static void Trace( |
| blink::Visitor* visitor, |
| const internal::ConcurrentBucket<KeyValuePair<Key, Value>>& self) { |
| TraceKeyValuePairInCollectionTrait<kWeakHandling, Key, Value, |
| Traits>::Trace(visitor, self.key(), |
| self.value()); |
| } |
| }; |
| |
| template <typename T> |
| struct IsWeak<internal::ConcurrentBucket<T>> : IsWeak<T> {}; |
| |
| } // namespace WTF |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_HASH_TABLE_BACKING_H_ |