Reviewers: oilpan-reviews, haraken
CL:
https://codereview.chromium.org/2007283002/Message:
PTAL
Part of:
1. Add checks for per thread heap
https://codereview.chromium.org/2012763002/2. This. Allow CrossThreadPersistent in collections
https://codereview.chromium.org/2007283002/3. Enable per thread heap for database thread
https://codereview.chromium.org/1909813002/Description:
Allow CrossThreadPersistent in collections
BUG=591606
Base URL:
https://chromium.googlesource.com/chromium/src.git@masterAffected files (+62, -5 lines):
M third_party/WebKit/Source/platform/heap/HeapAllocator.h
M third_party/WebKit/Source/platform/heap/Persistent.h
M third_party/WebKit/Source/platform/heap/PersistentNode.cpp
Index: third_party/WebKit/Source/platform/heap/HeapAllocator.h
diff --git a/third_party/WebKit/Source/platform/heap/HeapAllocator.h b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
index 40e0d381d90225e8c4bdae2271e9e72bf48ae07b..d6204e7fe75fd5e9453d5b83d2d6b8988956c799 100644
--- a/third_party/WebKit/Source/platform/heap/HeapAllocator.h
+++ b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
@@ -422,6 +422,14 @@ template <typename T> struct VectorTraits<blink::UntracedMember<T>> : VectorTrai
static const bool canMoveWithMemcpy = true;
};
+template <typename T> struct VectorTraits<blink::CrossThreadPersistent<T>> : VectorTraitsBase<blink::CrossThreadPersistent<T>> {
+ STATIC_ONLY(VectorTraits);
+ static const bool needsDestruction = true;
+ static const bool canInitializeWithMemset = false;
+ static const bool canClearUnusedSlotsWithMemset = false;
+ static const bool canMoveWithMemcpy = false;
+};
+
template <typename T> struct VectorTraits<blink::HeapVector<T, 0>> : VectorTraitsBase<blink::HeapVector<T, 0>> {
STATIC_ONLY(VectorTraits);
static const bool needsDestruction = false;
@@ -551,6 +559,33 @@ struct IsGarbageCollectedType<ListHashSetNode<T, blink::HeapListHashSetAllocator
static const bool value = true;
};
+template<typename T> struct HashTraits<blink::CrossThreadPersistent<T>> : SimpleClassHashTraits<blink::CrossThreadPersistent<T>> {
+ STATIC_ONLY(HashTraits);
+ // FIXME: The distinction between PeekInType and PassInType is there for
+ // the sake of the reference counting handles. When they are gone the two
+ // types can be merged into PassInType.
+ // FIXME: Implement proper const'ness for iterator types. Requires support
+ // in the marking Visitor.
+ using PeekInType = T*;
+ using PassInType = T*;
+ using IteratorGetType = blink::Member<T>*;
+ using IteratorConstGetType = const blink::CrossThreadPersistent<T>*;
+ using IteratorReferenceType = blink::CrossThreadPersistent<T>&;
+ using IteratorConstReferenceType = const blink::CrossThreadPersistent<T>&;
+ static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; }
+ static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return *x; }
+ // FIXME: Similarly, there is no need for a distinction between PeekOutType
+ // and PassOutType without reference counting.
+ using PeekOutType = T*;
+ using PassOutType = T*;
+
+ template<typename U>
+ static void store(const U& value, blink::CrossThreadPersistent<T>& storage) { storage = value; }
+
+ static PeekOutType peek(const blink::CrossThreadPersistent<T>& value) { return value; }
+ static PassOutType passOut(const blink::CrossThreadPersistent<T>& value) { return value; }
+};
+
} // namespace WTF
#endif
Index: third_party/WebKit/Source/platform/heap/Persistent.h
diff --git a/third_party/WebKit/Source/platform/heap/Persistent.h b/third_party/WebKit/Source/platform/heap/Persistent.h
index 8aa3708af2df13521feaaa734413965cde3ac299..64b03d3a5a5976412dda1f316530dca8c83291c0 100644
--- a/third_party/WebKit/Source/platform/heap/Persistent.h
+++ b/third_party/WebKit/Source/platform/heap/Persistent.h
@@ -77,12 +77,20 @@ public:
checkPointer();
}
+ PersistentBase(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(-1))
+ {
+ initialize();
+ checkPointer();
+ }
+
~PersistentBase()
{
uninitialize();
m_raw = nullptr;
}
+ bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>(-1); }
+
template<typename VisitorDispatcher>
void trace(VisitorDispatcher visitor)
{
@@ -184,7 +192,7 @@ private:
void initialize()
{
ASSERT(!m_persistentNode);
- if (!m_raw)
+ if (!m_raw || isHashTableDeletedValue())
return;
TraceCallback traceCallback = TraceMethodDelegate<PersistentBase<T, weaknessConfiguration, crossThreadnessConfiguration>, &PersistentBase<T, weaknessConfiguration, crossThreadnessConfiguration>::trace>::trampoline;
@@ -202,14 +210,15 @@ private:
void uninitialize()
{
+ if (!m_persistentNode)
+ return;
+
if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) {
if (acquireLoad(reinterpret_cast<void* volatile*>(&m_persistentNode)))
ProcessHeap::crossThreadPersistentRegion().freePersistentNode(m_persistentNode);
return;
}
- if (!m_persistentNode)
- return;
ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
ASSERT(state->checkThread());
// Persistent handle must be created and destructed in the same thread.
@@ -221,7 +230,7 @@ private:
void checkPointer()
{
#if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER)
- if (!m_raw)
+ if (!m_raw || isHashTableDeletedValue())
return;
// ThreadHeap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable
@@ -372,6 +381,7 @@ public:
CrossThreadPersistent(const CrossThreadPersistent<U>& other) : Parent(other) { }
template<typename U>
CrossThreadPersistent(const Member<U>& other) : Parent(other) { }
+ CrossThreadPersistent(WTF::HashTableDeletedValueType x) : Parent(x) { }
T* atomicGet() { return Parent::atomicGet(); }
@@ -682,6 +692,17 @@ template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
namespace WTF {
+template <typename T>
+struct CrossThreadPersistentHash : MemberHash<T> {
+ STATIC_ONLY(CrossThreadPersistentHash);
+};
+
+template <typename T>
+struct DefaultHash<blink::CrossThreadPersistent<T>> {
+ STATIC_ONLY(DefaultHash);
+ using Hash = CrossThreadPersistentHash<T>;
+};
+
template<typename T>
struct ParamStorageTraits<blink::WeakPersistentThisPointer<T>> {
STATIC_ONLY(ParamStorageTraits);
Index: third_party/WebKit/Source/platform/heap/PersistentNode.cpp
diff --git a/third_party/WebKit/Source/platform/heap/PersistentNode.cpp b/third_party/WebKit/Source/platform/heap/PersistentNode.cpp
index 2c512958fed0f56d3fa88e42fe2b6710c21e5b8d..615b6cb76a356fdcadac8dc0dd2a834005e16ddc 100644
--- a/third_party/WebKit/Source/platform/heap/PersistentNode.cpp
+++ b/third_party/WebKit/Source/platform/heap/PersistentNode.cpp
@@ -124,7 +124,8 @@ void PersistentRegion::tracePersistentNodes(Visitor* visitor, ShouldTraceCallbac
bool CrossThreadPersistentRegion::shouldTracePersistentNode(Visitor* visitor, PersistentNode* node)
{
CrossThreadPersistent<DummyGCBase>* persistent = reinterpret_cast<CrossThreadPersistent<DummyGCBase>*>(node->self());
- ASSERT(persistent);
+ DCHECK(persistent);
+ DCHECK(!persistent->isHashTableDeletedValue());
Address rawObject = reinterpret_cast<Address>(persistent->get());
if (!rawObject)
return false;