OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |