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

Side by Side Diff: Source/platform/heap/PersistentNode.h

Issue 1265103003: Invalidate cross-thread persistents on heap termination. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: clarify comments + style tweaks Created 5 years, 4 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef PersistentNode_h 5 #ifndef PersistentNode_h
6 #define PersistentNode_h 6 #define PersistentNode_h
7 7
8 #include "platform/PlatformExport.h" 8 #include "platform/PlatformExport.h"
9 #include "platform/heap/ThreadState.h" 9 #include "platform/heap/ThreadState.h"
10 #include "wtf/Assertions.h" 10 #include "wtf/Assertions.h"
(...skipping 26 matching lines...) Expand all
37 37
38 // Ideally the trace method should be virtual and automatically dispatch 38 // Ideally the trace method should be virtual and automatically dispatch
39 // to the most specific implementation. However having a virtual method 39 // to the most specific implementation. However having a virtual method
40 // on PersistentNode leads to too eager template instantiation with MSVC 40 // on PersistentNode leads to too eager template instantiation with MSVC
41 // which leads to include cycles. 41 // which leads to include cycles.
42 // Instead we call the constructor with a TraceCallback which knows the 42 // Instead we call the constructor with a TraceCallback which knows the
43 // type of the most specific child and calls trace directly. See 43 // type of the most specific child and calls trace directly. See
44 // TraceMethodDelegate in Visitor.h for how this is done. 44 // TraceMethodDelegate in Visitor.h for how this is done.
45 void tracePersistentNode(Visitor* visitor) 45 void tracePersistentNode(Visitor* visitor)
46 { 46 {
47 ASSERT(isValid());
47 ASSERT(!isUnused()); 48 ASSERT(!isUnused());
48 ASSERT(m_trace); 49 ASSERT(m_trace);
49 m_trace(visitor, m_self); 50 m_trace(visitor, m_self);
50 } 51 }
51 52
52 void initialize(void* self, TraceCallback trace) 53 void initialize(void* self, TraceCallback trace)
53 { 54 {
54 ASSERT(isUnused()); 55 ASSERT(isUnused());
55 m_self = self; 56 m_self = self;
56 m_trace = trace; 57 m_trace = trace;
(...skipping 13 matching lines...) Expand all
70 PersistentNode* node = reinterpret_cast<PersistentNode*>(m_self); 71 PersistentNode* node = reinterpret_cast<PersistentNode*>(m_self);
71 ASSERT(!node || node->isUnused()); 72 ASSERT(!node || node->isUnused());
72 return node; 73 return node;
73 } 74 }
74 75
75 bool isUnused() const 76 bool isUnused() const
76 { 77 {
77 return !m_trace; 78 return !m_trace;
78 } 79 }
79 80
81 bool isValid() const
82 {
83 return !(reinterpret_cast<uintptr_t>(m_self) & 0x1);
84 }
85
86 void invalidate()
87 {
88 m_self = reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(m_self) | 0x1);
haraken 2015/08/03 00:45:25 Or I'd prefer just clearing the pointer. The seman
sof 2015/08/03 08:30:04 Can do that instead, that is, clear out the underl
89 }
90
91 void* self() const
92 {
93 return m_self;
94 }
95
80 private: 96 private:
81 // If this PersistentNode is in use: 97 // If this PersistentNode is in use:
82 // - m_self points to the corresponding Persistent handle. 98 // - m_self points to the corresponding Persistent handle.
83 // - m_trace points to the trace method. 99 // - m_trace points to the trace method.
84 // If this PersistentNode is freed: 100 // If this PersistentNode is freed:
85 // - m_self points to the next freed PersistentNode. 101 // - m_self points to the next freed PersistentNode.
86 // - m_trace is nullptr. 102 // - m_trace is nullptr.
87 void* m_self; 103 void* m_self;
88 TraceCallback m_trace; 104 TraceCallback m_trace;
89 }; 105 };
90 106
91 struct PersistentNodeSlots final { 107 struct PersistentNodeSlots final {
92 private: 108 private:
93 static const int slotCount = 256; 109 static const int slotCount = 256;
94 PersistentNodeSlots* m_next; 110 PersistentNodeSlots* m_next;
95 PersistentNode m_slot[slotCount]; 111 PersistentNode m_slot[slotCount];
96 friend class PersistentRegion; 112 friend class PersistentRegion;
113 friend class CrossThreadPersistentRegion;
97 }; 114 };
98 115
99 // PersistentRegion provides a region of PersistentNodes. PersistentRegion 116 // PersistentRegion provides a region of PersistentNodes. PersistentRegion
100 // holds a linked list of PersistentNodeSlots, each of which stores 117 // holds a linked list of PersistentNodeSlots, each of which stores
101 // a predefined number of PersistentNodes. You can call allocatePersistentNode/ 118 // a predefined number of PersistentNodes. You can call allocatePersistentNode/
102 // freePersistentNode to allocate/free a PersistentNode on the region. 119 // freePersistentNode to allocate/free a PersistentNode on the region.
103 class PLATFORM_EXPORT PersistentRegion final { 120 class PLATFORM_EXPORT PersistentRegion final {
104 public: 121 public:
105 PersistentRegion() 122 PersistentRegion()
106 : m_freeListHead(nullptr) 123 : m_freeListHead(nullptr)
(...skipping 25 matching lines...) Expand all
132 persistentNode->setFreeListNext(m_freeListHead); 149 persistentNode->setFreeListNext(m_freeListHead);
133 m_freeListHead = persistentNode; 150 m_freeListHead = persistentNode;
134 #if ENABLE(ASSERT) 151 #if ENABLE(ASSERT)
135 --m_persistentCount; 152 --m_persistentCount;
136 #endif 153 #endif
137 } 154 }
138 void tracePersistentNodes(Visitor*); 155 void tracePersistentNodes(Visitor*);
139 int numberOfPersistents(); 156 int numberOfPersistents();
140 157
141 private: 158 private:
159 friend CrossThreadPersistentRegion;
160
142 void ensurePersistentNodeSlots(void*, TraceCallback); 161 void ensurePersistentNodeSlots(void*, TraceCallback);
143 162
144 PersistentNode* m_freeListHead; 163 PersistentNode* m_freeListHead;
145 PersistentNodeSlots* m_slots; 164 PersistentNodeSlots* m_slots;
146 #if ENABLE(ASSERT) 165 #if ENABLE(ASSERT)
147 int m_persistentCount; 166 int m_persistentCount;
148 #endif 167 #endif
149 }; 168 };
150 169
151 class CrossThreadPersistentRegion final { 170 class CrossThreadPersistentRegion final {
(...skipping 11 matching lines...) Expand all
163 MutexLocker lock(m_mutex); 182 MutexLocker lock(m_mutex);
164 m_persistentRegion->freePersistentNode(persistentNode); 183 m_persistentRegion->freePersistentNode(persistentNode);
165 } 184 }
166 185
167 void tracePersistentNodes(Visitor* visitor) 186 void tracePersistentNodes(Visitor* visitor)
168 { 187 {
169 MutexLocker lock(m_mutex); 188 MutexLocker lock(m_mutex);
170 m_persistentRegion->tracePersistentNodes(visitor); 189 m_persistentRegion->tracePersistentNodes(visitor);
171 } 190 }
172 191
192 void prepareForThreadStateTermination(ThreadState*);
193
173 private: 194 private:
174 // We don't make CrossThreadPersistentRegion inherit from PersistentRegion 195 // We don't make CrossThreadPersistentRegion inherit from PersistentRegion
175 // because we don't want to virtualize performance-sensitive methods 196 // because we don't want to virtualize performance-sensitive methods
176 // such as PersistentRegion::allocate/freePersistentNode. 197 // such as PersistentRegion::allocate/freePersistentNode.
177 OwnPtr<PersistentRegion> m_persistentRegion; 198 OwnPtr<PersistentRegion> m_persistentRegion;
178 Mutex m_mutex; 199 Mutex m_mutex;
179 }; 200 };
180 201
181 } // namespace blink 202 } // namespace blink
182 203
183 #endif 204 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698