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

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

Issue 1213133002: Oilpan: Reduce sizeof(Persistent) to 16 byte (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 | « Source/platform/heap/HeapTest.cpp ('k') | Source/platform/heap/PersistentNode.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/platform/heap/PersistentNode.h
diff --git a/Source/platform/heap/PersistentNode.h b/Source/platform/heap/PersistentNode.h
new file mode 100644
index 0000000000000000000000000000000000000000..fa18fa32cff10145a0f7fe1bd0dece9d240dd449
--- /dev/null
+++ b/Source/platform/heap/PersistentNode.h
@@ -0,0 +1,183 @@
+// Copyright 2015 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 PersistentNode_h
+#define PersistentNode_h
+
+#include "platform/PlatformExport.h"
+#include "platform/heap/ThreadState.h"
+#include "wtf/Assertions.h"
+#include "wtf/MainThread.h"
+#include "wtf/ThreadingPrimitives.h"
+
+namespace blink {
+
+class PersistentNode final {
+public:
+ PersistentNode()
+ : m_self(nullptr)
+ , m_trace(nullptr)
+ {
+ ASSERT(isUnused());
+ }
+
+ ~PersistentNode()
+ {
+ // If you hit this assert, it means that the thread finished
+ // without clearing persistent handles that the thread created.
+ // We don't enable the assert for the main thread because the
+ // main thread finishes without clearing all persistent handles.
+ ASSERT(isMainThread() || isUnused());
+ }
+
+ // It is dangrous to copy the PersistentNode because it breaks the
+ // free list.
+ PersistentNode& operator=(const PersistentNode& otherref) = delete;
+
+ // 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
+ // which leads to include cycles.
+ // 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 tracePersistentNode(Visitor* visitor)
+ {
+ ASSERT(!isUnused());
+ ASSERT(m_trace);
+ m_trace(visitor, m_self);
+ }
+
+ void initialize(void* self, TraceCallback trace)
+ {
+ ASSERT(isUnused());
+ m_self = self;
+ m_trace = trace;
+ }
+
+ void setFreeListNext(PersistentNode* node)
+ {
+ ASSERT(!node || node->isUnused());
+ m_self = node;
+ m_trace = nullptr;
+ ASSERT(isUnused());
+ }
+
+ PersistentNode* freeListNext()
+ {
+ ASSERT(isUnused());
+ PersistentNode* node = reinterpret_cast<PersistentNode*>(m_self);
+ ASSERT(!node || node->isUnused());
+ return node;
+ }
+
+ bool isUnused() const
+ {
+ return !m_trace;
+ }
+
+private:
+ // If this PersistentNode is in use:
+ // - m_self points to the corresponding Persistent handle.
+ // - m_trace points to the trace method.
+ // If this PersistentNode is freed:
+ // - m_self points to the next freed PersistentNode.
+ // - m_trace is nullptr.
+ void* m_self;
+ TraceCallback m_trace;
+};
+
+struct PersistentNodeSlots final {
+private:
+ static const int slotCount = 256;
+ PersistentNodeSlots* m_next;
+ PersistentNode m_slot[slotCount];
+ friend class PersistentRegion;
+};
+
+// PersistentRegion provides a region of PersistentNodes. PersistentRegion
+// holds a linked list of PersistentNodeSlots, each of which stores
+// a predefined number of PersistentNodes. You can call allocatePersistentNode/
+// freePersistentNode to allocate/free a PersistentNode on the region.
+class PLATFORM_EXPORT PersistentRegion final {
+public:
+ PersistentRegion()
+ : m_freeListHead(nullptr)
+ , m_slots(nullptr)
+#if ENABLE(ASSERT)
+ , m_persistentCount(0)
+#endif
+ {
+ }
+ ~PersistentRegion();
+
+ PersistentNode* allocatePersistentNode(void* self, TraceCallback trace)
+ {
+#if ENABLE(ASSERT)
+ ++m_persistentCount;
+#endif
+ if (UNLIKELY(!m_freeListHead))
+ ensurePersistentNodeSlots(self, trace);
+ ASSERT(m_freeListHead);
+ PersistentNode* node = m_freeListHead;
+ m_freeListHead = m_freeListHead->freeListNext();
+ node->initialize(self, trace);
+ ASSERT(!node->isUnused());
+ return node;
+ }
+ void freePersistentNode(PersistentNode* persistentNode)
+ {
+ ASSERT(m_persistentCount > 0);
+ persistentNode->setFreeListNext(m_freeListHead);
+ m_freeListHead = persistentNode;
+#if ENABLE(ASSERT)
+ --m_persistentCount;
+#endif
+ }
+ void tracePersistentNodes(Visitor*);
+ int numberOfPersistents();
+
+private:
+ void ensurePersistentNodeSlots(void*, TraceCallback);
+
+ PersistentNode* m_freeListHead;
+ PersistentNodeSlots* m_slots;
+#if ENABLE(ASSERT)
+ int m_persistentCount;
+#endif
+};
+
+class CrossThreadPersistentRegion final {
+public:
+ CrossThreadPersistentRegion() : m_persistentRegion(adoptPtr(new PersistentRegion)) { }
+
+ PersistentNode* allocatePersistentNode(void* self, TraceCallback trace)
+ {
+ MutexLocker lock(m_mutex);
+ return m_persistentRegion->allocatePersistentNode(self, trace);
+ }
+
+ void freePersistentNode(PersistentNode* persistentNode)
+ {
+ MutexLocker lock(m_mutex);
+ m_persistentRegion->freePersistentNode(persistentNode);
+ }
+
+ void tracePersistentNodes(Visitor* visitor)
+ {
+ MutexLocker lock(m_mutex);
+ m_persistentRegion->tracePersistentNodes(visitor);
+ }
+
+private:
+ // We don't make CrossThreadPersistentRegion inherit from PersistentRegion
+ // because we don't want to virtualize performance-sensitive methods
+ // such as PersistentRegion::allocate/freePersistentNode.
+ OwnPtr<PersistentRegion> m_persistentRegion;
+ Mutex m_mutex;
+};
+
+} // namespace blink
+
+#endif
« no previous file with comments | « Source/platform/heap/HeapTest.cpp ('k') | Source/platform/heap/PersistentNode.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698