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

Side by Side 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, 5 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef PersistentNode_h
6 #define PersistentNode_h
7
8 #include "platform/heap/ThreadState.h"
9 #include "wtf/Assertions.h"
10 #include "wtf/MainThread.h"
11 #include "wtf/ThreadingPrimitives.h"
12
13 namespace blink {
14
15 class PersistentNode final {
16 public:
17 PersistentNode()
18 : m_self(nullptr)
19 , m_trace(nullptr)
20 {
21 ASSERT(isFree());
22 }
23
24 ~PersistentNode()
25 {
26 // If you hit this assert, it means that the thread finished
27 // without clearing persistent handles that the thread created.
28 // We don't enable the assert for the main thread because the
29 // main thread finishes without clearing all persistent handles.
30 ASSERT(isMainThread() || isFree());
31 }
32
33 // It is dangrous to copy the PersistentNode because it breaks the
34 // free list.
35 PersistentNode& operator=(const PersistentNode& otherref) = delete;
36
37 // Ideally the trace method should be virtual and automatically dispatch
38 // to the most specific implementation. However having a virtual method
39 // on PersistentNode leads to too eager template instantiation with MSVC
40 // which leads to include cycles.
41 // Instead we call the constructor with a TraceCallback which knows the
42 // type of the most specific child and calls trace directly. See
43 // TraceMethodDelegate in Visitor.h for how this is done.
44 void tracePersistentNode(Visitor* visitor)
45 {
46 ASSERT(!isFree());
47 ASSERT(m_trace);
48 m_trace(visitor, m_self);
49 }
50
51 void initialize(void* self, TraceCallback trace)
52 {
53 ASSERT(isFree());
54 m_self = self;
55 m_trace = trace;
56 }
57
58 void setFreeNext(PersistentNode* node)
59 {
60 ASSERT(!node || node->isFree());
61 m_self = node;
62 m_trace = nullptr;
63 ASSERT(isFree());
64 }
65
66 PersistentNode* freeNext()
67 {
68 ASSERT(isFree());
69 PersistentNode* node = reinterpret_cast<PersistentNode*>(m_self);
70 ASSERT(!node || node->isFree());
71 return node;
72 }
73
74 bool isFree() const
sof 2015/06/30 09:19:39 "free" feels a bit overloaded in this context - "u
haraken 2015/06/30 09:51:32 Done.
75 {
76 return !m_trace;
77 }
78
79 private:
80 // If this PersistentNode is in use:
81 // - m_self points to the corresponding Persistent handle.
82 // - m_trace points to the trace method.
83 // If this PersistentNode is freed:
84 // - m_self points to the next freed PersistentNode.
85 // - m_trace is nullptr.
86 void* m_self;
87 TraceCallback m_trace;
88 };
89
90 struct PersistentNodeSlots final {
91 private:
92 static const int slotCount = 256;
93 PersistentNodeSlots* m_next;
94 PersistentNode m_slot[slotCount];
95 friend class PersistentRegion;
96 };
97
98 class PersistentRegion final {
sof 2015/06/30 09:19:39 Could you add a comment outlining what this provid
99 public:
100 PersistentRegion()
101 : m_freeHead(nullptr)
102 , m_slots(nullptr)
103 #if ENABLE(ASSERT)
104 , m_numberOfPersistents(0)
105 #endif
106 {
107 }
108 ~PersistentRegion();
109
110 PersistentNode* allocatePersistentNode(void* self, TraceCallback trace)
111 {
112 #if ENABLE(ASSERT)
113 ++m_numberOfPersistents;
114 #endif
115 if (UNLIKELY(!m_freeHead))
116 ensurePersistentNodeSlots(self, trace);
117 ASSERT(m_freeHead);
118 PersistentNode* node = m_freeHead;
119 m_freeHead = m_freeHead->freeNext();
120 node->initialize(self, trace);
121 ASSERT(!node->isFree());
122 return node;
123 }
124 void ensurePersistentNodeSlots(void*, TraceCallback);
sof 2015/06/30 09:19:39 make this private?
haraken 2015/06/30 09:51:32 Done.
125 void freePersistentNode(PersistentNode* persistentNode)
126 {
127 ASSERT(m_numberOfPersistents > 0);
128 persistentNode->setFreeNext(m_freeHead);
129 m_freeHead = persistentNode;
130 #if ENABLE(ASSERT)
131 --m_numberOfPersistents;
132 #endif
133 }
134 void tracePersistentNodes(Visitor*);
135 int numberOfPersistents();
136
137 private:
138 PersistentNode* m_freeHead;
139 PersistentNodeSlots* m_slots;
140 #if ENABLE(ASSERT)
141 int m_numberOfPersistents;
sof 2015/06/30 09:19:39 Did you consider caching this count outside of ENA
haraken 2015/06/30 09:51:32 At first I did this, but it added extra overhead t
142 #endif
143 };
144
145 class CrossThreadPersistentRegion final {
146 public:
147 CrossThreadPersistentRegion() : m_persistentRegion(adoptPtr(new PersistentRe gion)) { }
148
149 PersistentNode* allocatePersistentNode(void* self, TraceCallback trace)
150 {
151 MutexLocker lock(m_mutex);
152 return m_persistentRegion->allocatePersistentNode(self, trace);
153 }
154
155 void freePersistentNode(PersistentNode* persistentNode)
156 {
157 MutexLocker lock(m_mutex);
158 m_persistentRegion->freePersistentNode(persistentNode);
159 }
160
161 void tracePersistentNodes(Visitor* visitor)
162 {
163 MutexLocker lock(m_mutex);
164 m_persistentRegion->tracePersistentNodes(visitor);
165 }
166
167 private:
168 // We don't make CrossThreadPersistentRegion inherit from PersistentRegion
169 // because we don't want to virtualize performance-sensitive methods
170 // such as PersistentRegion::allocate/freePersistentNode.
171 OwnPtr<PersistentRegion> m_persistentRegion;
172 Mutex m_mutex;
173 };
174
175 } // namespace blink
176
177 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698