Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(645)

Unified Diff: Source/platform/heap/Handle.h

Issue 1168503008: Oilpan: Remove PersistentBase (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | Source/platform/heap/ThreadState.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/platform/heap/Handle.h
diff --git a/Source/platform/heap/Handle.h b/Source/platform/heap/Handle.h
index 814caa654f8900893bed30481f6248a3938ac041..54996df08f687bb05895449023c1c64c6759f56c 100644
--- a/Source/platform/heap/Handle.h
+++ b/Source/platform/heap/Handle.h
@@ -64,6 +64,12 @@ public:
m_trace = nullptr;
}
+ // This operator= is important. Without having the operator=, m_next and
+ // m_prev are inproperly copied and it breaks the link list of the
+ // persistent handles.
+ inline PersistentNode& operator=(const PersistentNode& otherref) { return *this; }
+
+private:
// Ideally the trace method should be virtual and automatically dispatch
// to the most specific implementation. However having a virtual method
// on PersistentNode leads to too eager template instantiation with MSVC
@@ -71,106 +77,30 @@ public:
// Instead we call the constructor with a TraceCallback which knows the
// type of the most specific child and calls trace directly. See
// TraceMethodDelegate in Visitor.h for how this is done.
- void trace(Visitor* visitor)
+ void tracePersistentNode(Visitor* visitor)
{
m_trace(visitor, this);
}
-protected:
TraceCallback m_trace;
-
-private:
PersistentNode* m_next;
PersistentNode* m_prev;
- template<typename RootsAccessor, typename Owner> friend class PersistentBase;
+ template<typename T> friend class CrossThreadPersistent;
+ template<typename T> friend class Persistent;
+ template<typename Collection> friend class PersistentHeapCollectionBase;
friend class PersistentAnchor;
friend class ThreadState;
};
-// RootsAccessor for Persistent that provides access to thread-local list
-// of persistent handles. Can only be used to create handles that
-// are constructed and destructed on the same thread.
-template<ThreadAffinity Affinity>
-class ThreadLocalPersistents {
-public:
- static PersistentNode* roots() { return state()->roots(); }
-
- // No locking required. Just check that we are at the right thread.
- class Lock {
- public:
- Lock() { state()->checkThread(); }
- };
-
-private:
- static ThreadState* state() { return ThreadStateFor<Affinity>::state(); }
-};
-
-// RootsAccessor for Persistent that provides synchronized access to global
-// list of persistent handles. Can be used for persistent handles that are
-// passed between threads.
-class GlobalPersistents {
-public:
- static PersistentNode* roots() { return &ThreadState::globalRoots(); }
-
- class Lock {
- public:
- Lock() : m_locker(ThreadState::globalRootsMutex()) { }
- private:
- MutexLocker m_locker;
- };
-};
-
-// Base class for persistent handles. RootsAccessor specifies which list to
-// link resulting handle into. Owner specifies the class containing trace
-// method.
-template<typename RootsAccessor, typename Owner>
-class PersistentBase : public PersistentNode {
-public:
- NO_LAZY_SWEEP_SANITIZE_ADDRESS
- ~PersistentBase()
- {
- typename RootsAccessor::Lock lock;
- ASSERT(m_roots == RootsAccessor::roots()); // Check that the thread is using the same roots list.
- ASSERT(isHeapObjectAlive());
- ASSERT(m_next->isHeapObjectAlive());
- ASSERT(m_prev->isHeapObjectAlive());
- m_next->m_prev = m_prev;
- m_prev->m_next = m_next;
- }
-
-protected:
- inline PersistentBase()
- : PersistentNode(TraceMethodDelegate<Owner, &Owner::trace>::trampoline)
-#if ENABLE(ASSERT)
- , m_roots(RootsAccessor::roots())
-#endif
- {
- // Persistent must belong to a thread that will GC it.
- ASSERT(m_roots == GlobalPersistents::roots() || ThreadState::current());
- typename RootsAccessor::Lock lock;
- m_prev = RootsAccessor::roots();
- m_next = m_prev->m_next;
- m_prev->m_next = this;
- m_next->m_prev = this;
- }
-
- inline PersistentBase& operator=(const PersistentBase& otherref) { return *this; }
-
-#if ENABLE(ASSERT)
-private:
- PersistentNode* m_roots;
-#endif
-};
-
// A dummy Persistent handle that ensures the list of persistents is never null.
// This removes a test from a hot path.
class PersistentAnchor : public PersistentNode {
public:
- void trace(Visitor* visitor)
+ void tracePersistentNodes(Visitor* visitor)
{
for (PersistentNode* current = m_next; current != this; current = current->m_next)
- current->trace(visitor);
+ current->tracePersistentNode(visitor);
}
int numberOfPersistents()
@@ -189,6 +119,12 @@ public:
// this point.
}
+ template<typename VisitorDispatcher>
+ void trace(VisitorDispatcher visitor)
+ {
+ ASSERT_NOT_REACHED();
+ }
+
private:
PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &PersistentAnchor::trace>::trampoline)
{
@@ -199,9 +135,6 @@ private:
friend class ThreadState;
};
-template<typename T>
-class CrossThreadPersistent;
-
// Persistent handles are used to store pointers into the
// managed heap. As long as the Persistent handle is alive
// the GC will keep the object pointed to alive. Persistent
@@ -216,47 +149,59 @@ class CrossThreadPersistent;
//
// We have to construct and destruct Persistent in the same thread.
template<typename T>
-class Persistent : public PersistentBase<ThreadLocalPersistents<ThreadingTrait<T>::Affinity>, Persistent<T>> {
+class Persistent : public PersistentNode {
public:
- Persistent() : m_raw(nullptr) { }
+ Persistent() : PersistentNode(TraceMethodDelegate<Persistent<T>, &Persistent<T>::trace>::trampoline), m_raw(nullptr)
+ {
+ initialize();
+ }
- Persistent(std::nullptr_t) : m_raw(nullptr) { }
+ Persistent(std::nullptr_t) : PersistentNode(TraceMethodDelegate<Persistent<T>, &Persistent<T>::trace>::trampoline), m_raw(nullptr)
+ {
+ initialize();
+ }
- Persistent(T* raw) : m_raw(raw)
+ Persistent(T* raw) : PersistentNode(TraceMethodDelegate<Persistent<T>, &Persistent<T>::trace>::trampoline), m_raw(raw)
{
+ initialize();
checkPointer();
recordBacktrace();
}
- explicit Persistent(T& raw) : m_raw(&raw)
+ Persistent(T& raw) : PersistentNode(TraceMethodDelegate<Persistent<T>, &Persistent<T>::trace>::trampoline), m_raw(&raw)
{
+ initialize();
checkPointer();
recordBacktrace();
}
- Persistent(const Persistent& other) : m_raw(other)
+ Persistent(const Persistent& other) : PersistentNode(TraceMethodDelegate<Persistent<T>, &Persistent<T>::trace>::trampoline), m_raw(other)
{
+ initialize();
checkPointer();
recordBacktrace();
}
template<typename U>
- Persistent(const Persistent<U>& other) : m_raw(other)
+ Persistent(const Persistent<U>& other) : PersistentNode(TraceMethodDelegate<Persistent<T>, &Persistent<T>::trace>::trampoline), m_raw(other)
{
+ initialize();
checkPointer();
recordBacktrace();
}
template<typename U>
- Persistent(const Member<U>& other) : m_raw(other)
+ Persistent(const Member<U>& other) : PersistentNode(TraceMethodDelegate<Persistent<T>, &Persistent<T>::trace>::trampoline), m_raw(other)
{
+ initialize();
checkPointer();
recordBacktrace();
}
template<typename U>
- Persistent(const RawPtr<U>& other) : m_raw(other.get())
+ Persistent(const RawPtr<U>& other) : PersistentNode(TraceMethodDelegate<Persistent<T>, &Persistent<T>::trace>::trampoline), m_raw(other.get())
{
+ initialize();
checkPointer();
recordBacktrace();
}
@@ -265,6 +210,7 @@ public:
virtual ~Persistent()
{
+ uninitialize();
m_raw = nullptr;
}
@@ -348,6 +294,25 @@ public:
T* get() const { return m_raw; }
private:
+ void initialize()
+ {
+ ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
+ state->checkThread();
+ m_prev = state->roots();
+ m_next = m_prev->m_next;
+ m_prev->m_next = this;
+ m_next->m_prev = this;
+ }
+
+ void uninitialize()
+ {
+ ASSERT(isHeapObjectAlive());
+ ASSERT(m_next->isHeapObjectAlive());
+ ASSERT(m_prev->isHeapObjectAlive());
+ m_next->m_prev = m_prev;
+ m_prev->m_next = m_next;
+ }
+
void checkPointer()
{
#if ENABLE(ASSERT)
@@ -383,47 +348,59 @@ private:
// Unlike Persistent, we can destruct a CrossThreadPersistent in a thread
// different from the construction thread.
template<typename T>
-class CrossThreadPersistent : public PersistentBase<GlobalPersistents, CrossThreadPersistent<T>> {
+class CrossThreadPersistent : public PersistentNode {
public:
- CrossThreadPersistent() : m_raw(nullptr) { }
+ CrossThreadPersistent() : PersistentNode(TraceMethodDelegate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(nullptr)
+ {
+ initialize();
+ }
- CrossThreadPersistent(std::nullptr_t) : m_raw(nullptr) { }
+ CrossThreadPersistent(std::nullptr_t) : PersistentNode(TraceMethodDelegate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(nullptr)
+ {
+ initialize();
+ }
- CrossThreadPersistent(T* raw) : m_raw(raw)
+ CrossThreadPersistent(T* raw) : PersistentNode(TraceMethodDelegate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(raw)
{
+ initialize();
checkPointer();
recordBacktrace();
}
- explicit CrossThreadPersistent(T& raw) : m_raw(&raw)
+ CrossThreadPersistent(T& raw) : PersistentNode(TraceMethodDelegate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(&raw)
{
+ initialize();
checkPointer();
recordBacktrace();
}
- CrossThreadPersistent(const CrossThreadPersistent& other) : m_raw(other)
+ CrossThreadPersistent(const CrossThreadPersistent& other) : PersistentNode(TraceMethodDelegate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(other)
{
+ initialize();
checkPointer();
recordBacktrace();
}
template<typename U>
- CrossThreadPersistent(const CrossThreadPersistent<U>& other) : m_raw(other)
+ CrossThreadPersistent(const CrossThreadPersistent<U>& other) : PersistentNode(TraceMethodDelegate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(other)
{
+ initialize();
checkPointer();
recordBacktrace();
}
template<typename U>
- CrossThreadPersistent(const Member<U>& other) : m_raw(other)
+ CrossThreadPersistent(const Member<U>& other) : PersistentNode(TraceMethodDelegate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(other)
{
+ initialize();
checkPointer();
recordBacktrace();
}
template<typename U>
- CrossThreadPersistent(const RawPtr<U>& other) : m_raw(other.get())
+ CrossThreadPersistent(const RawPtr<U>& other) : PersistentNode(TraceMethodDelegate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(other.get())
{
+ initialize();
checkPointer();
recordBacktrace();
}
@@ -432,6 +409,7 @@ public:
virtual ~CrossThreadPersistent()
{
+ uninitialize();
m_raw = nullptr;
}
@@ -515,6 +493,25 @@ public:
T* get() const { return m_raw; }
private:
+ void initialize()
+ {
+ MutexLocker m_locker(ThreadState::globalRootsMutex());
+ m_prev = &ThreadState::globalRoots();
+ m_next = m_prev->m_next;
+ m_prev->m_next = this;
+ m_next->m_prev = this;
+ }
+
+ void uninitialize()
+ {
+ MutexLocker m_locker(ThreadState::globalRootsMutex());
+ ASSERT(isHeapObjectAlive());
+ ASSERT(m_next->isHeapObjectAlive());
+ ASSERT(m_prev->isHeapObjectAlive());
+ m_next->m_prev = m_prev;
+ m_prev->m_next = m_next;
+ }
+
void checkPointer()
{
#if ENABLE(ASSERT)
@@ -547,21 +544,33 @@ private:
};
// FIXME: derive affinity based on the collection.
-template<typename Collection, ThreadAffinity Affinity = AnyThread>
-class PersistentHeapCollectionBase
- : public Collection
- , public PersistentBase<ThreadLocalPersistents<Affinity>, PersistentHeapCollectionBase<Collection, Affinity>> {
+template<typename Collection>
+class PersistentHeapCollectionBase : public Collection, public PersistentNode {
// We overload the various new and delete operators with using the WTF DefaultAllocator to ensure persistent
// heap collections are always allocated off-heap. This allows persistent collections to be used in
// DEFINE_STATIC_LOCAL et. al.
WTF_USE_ALLOCATOR(PersistentHeapCollectionBase, WTF::DefaultAllocator);
public:
- PersistentHeapCollectionBase() { }
+ PersistentHeapCollectionBase() : PersistentNode(TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, &PersistentHeapCollectionBase<Collection>::trace>::trampoline)
+ {
+ initialize();
+ }
- PersistentHeapCollectionBase(const PersistentHeapCollectionBase& other) : Collection(other) { }
+ PersistentHeapCollectionBase(const PersistentHeapCollectionBase& other) : Collection(other), PersistentNode(TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, &PersistentHeapCollectionBase<Collection>::trace>::trampoline)
+ {
+ initialize();
+ }
template<typename OtherCollection>
- PersistentHeapCollectionBase(const OtherCollection& other) : Collection(other) { }
+ PersistentHeapCollectionBase(const OtherCollection& other) : Collection(other), PersistentNode(TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, &PersistentHeapCollectionBase<Collection>::trace>::trampoline)
+ {
+ initialize();
+ }
+
+ ~PersistentHeapCollectionBase()
+ {
+ uninitialize();
+ }
template<typename VisitorDispatcher>
void trace(VisitorDispatcher visitor)
@@ -572,6 +581,25 @@ public:
#endif
visitor->trace(*static_cast<Collection*>(this));
}
+
+private:
+ void initialize()
+ {
+ ThreadState* state = ThreadState::current();
+ m_prev = state->roots();
+ m_next = m_prev->m_next;
+ m_prev->m_next = this;
+ m_next->m_prev = this;
+ }
+
+ void uninitialize()
+ {
+ ASSERT(isHeapObjectAlive());
+ ASSERT(m_next->isHeapObjectAlive());
+ ASSERT(m_prev->isHeapObjectAlive());
+ m_next->m_prev = m_prev;
+ m_prev->m_next = m_next;
+ }
};
template<
« no previous file with comments | « no previous file | Source/platform/heap/ThreadState.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698