| 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/Allocator.h" | 10 #include "wtf/Allocator.h" |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 // holds a linked list of PersistentNodeSlots, each of which stores | 100 // holds a linked list of PersistentNodeSlots, each of which stores |
| 101 // a predefined number of PersistentNodes. You can call allocatePersistentNode/ | 101 // a predefined number of PersistentNodes. You can call allocatePersistentNode/ |
| 102 // freePersistentNode to allocate/free a PersistentNode on the region. | 102 // freePersistentNode to allocate/free a PersistentNode on the region. |
| 103 class PLATFORM_EXPORT PersistentRegion final { | 103 class PLATFORM_EXPORT PersistentRegion final { |
| 104 USING_FAST_MALLOC(PersistentRegion); | 104 USING_FAST_MALLOC(PersistentRegion); |
| 105 | 105 |
| 106 public: | 106 public: |
| 107 PersistentRegion() | 107 PersistentRegion() |
| 108 : m_freeListHead(nullptr), | 108 : m_freeListHead(nullptr), |
| 109 m_slots(nullptr) | 109 m_slots(nullptr) |
| 110 #if ENABLE(ASSERT) | 110 #if DCHECK_IS_ON() |
| 111 , | 111 , |
| 112 m_persistentCount(0) | 112 m_persistentCount(0) |
| 113 #endif | 113 #endif |
| 114 { | 114 { |
| 115 } | 115 } |
| 116 ~PersistentRegion(); | 116 ~PersistentRegion(); |
| 117 | 117 |
| 118 PersistentNode* allocatePersistentNode(void* self, TraceCallback trace) { | 118 PersistentNode* allocatePersistentNode(void* self, TraceCallback trace) { |
| 119 #if ENABLE(ASSERT) | 119 #if DCHECK_IS_ON() |
| 120 ++m_persistentCount; | 120 ++m_persistentCount; |
| 121 #endif | 121 #endif |
| 122 if (UNLIKELY(!m_freeListHead)) | 122 if (UNLIKELY(!m_freeListHead)) |
| 123 ensurePersistentNodeSlots(self, trace); | 123 ensurePersistentNodeSlots(self, trace); |
| 124 ASSERT(m_freeListHead); | 124 ASSERT(m_freeListHead); |
| 125 PersistentNode* node = m_freeListHead; | 125 PersistentNode* node = m_freeListHead; |
| 126 m_freeListHead = m_freeListHead->freeListNext(); | 126 m_freeListHead = m_freeListHead->freeListNext(); |
| 127 node->initialize(self, trace); | 127 node->initialize(self, trace); |
| 128 ASSERT(!node->isUnused()); | 128 ASSERT(!node->isUnused()); |
| 129 return node; | 129 return node; |
| 130 } | 130 } |
| 131 | 131 |
| 132 void freePersistentNode(PersistentNode* persistentNode) { | 132 void freePersistentNode(PersistentNode* persistentNode) { |
| 133 ASSERT(m_persistentCount > 0); | 133 ASSERT(m_persistentCount > 0); |
| 134 persistentNode->setFreeListNext(m_freeListHead); | 134 persistentNode->setFreeListNext(m_freeListHead); |
| 135 m_freeListHead = persistentNode; | 135 m_freeListHead = persistentNode; |
| 136 #if ENABLE(ASSERT) | 136 #if DCHECK_IS_ON() |
| 137 --m_persistentCount; | 137 --m_persistentCount; |
| 138 #endif | 138 #endif |
| 139 } | 139 } |
| 140 | 140 |
| 141 static bool shouldTracePersistentNode(Visitor*, PersistentNode*) { | 141 static bool shouldTracePersistentNode(Visitor*, PersistentNode*) { |
| 142 return true; | 142 return true; |
| 143 } | 143 } |
| 144 | 144 |
| 145 void releasePersistentNode(PersistentNode*, | 145 void releasePersistentNode(PersistentNode*, |
| 146 ThreadState::PersistentClearCallback); | 146 ThreadState::PersistentClearCallback); |
| 147 using ShouldTraceCallback = bool (*)(Visitor*, PersistentNode*); | 147 using ShouldTraceCallback = bool (*)(Visitor*, PersistentNode*); |
| 148 void tracePersistentNodes( | 148 void tracePersistentNodes( |
| 149 Visitor*, | 149 Visitor*, |
| 150 ShouldTraceCallback = PersistentRegion::shouldTracePersistentNode); | 150 ShouldTraceCallback = PersistentRegion::shouldTracePersistentNode); |
| 151 int numberOfPersistents(); | 151 int numberOfPersistents(); |
| 152 | 152 |
| 153 private: | 153 private: |
| 154 friend CrossThreadPersistentRegion; | 154 friend CrossThreadPersistentRegion; |
| 155 | 155 |
| 156 void ensurePersistentNodeSlots(void*, TraceCallback); | 156 void ensurePersistentNodeSlots(void*, TraceCallback); |
| 157 | 157 |
| 158 PersistentNode* m_freeListHead; | 158 PersistentNode* m_freeListHead; |
| 159 PersistentNodeSlots* m_slots; | 159 PersistentNodeSlots* m_slots; |
| 160 #if ENABLE(ASSERT) | 160 #if DCHECK_IS_ON() |
| 161 int m_persistentCount; | 161 int m_persistentCount; |
| 162 #endif | 162 #endif |
| 163 }; | 163 }; |
| 164 | 164 |
| 165 class CrossThreadPersistentRegion final { | 165 class CrossThreadPersistentRegion final { |
| 166 USING_FAST_MALLOC(CrossThreadPersistentRegion); | 166 USING_FAST_MALLOC(CrossThreadPersistentRegion); |
| 167 | 167 |
| 168 public: | 168 public: |
| 169 CrossThreadPersistentRegion() | 169 CrossThreadPersistentRegion() |
| 170 : m_persistentRegion(wrapUnique(new PersistentRegion)) {} | 170 : m_persistentRegion(wrapUnique(new PersistentRegion)) {} |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 #endif | 217 #endif |
| 218 m_persistentRegion->tracePersistentNodes( | 218 m_persistentRegion->tracePersistentNodes( |
| 219 visitor, CrossThreadPersistentRegion::shouldTracePersistentNode); | 219 visitor, CrossThreadPersistentRegion::shouldTracePersistentNode); |
| 220 } | 220 } |
| 221 | 221 |
| 222 void prepareForThreadStateTermination(ThreadState*); | 222 void prepareForThreadStateTermination(ThreadState*); |
| 223 | 223 |
| 224 NO_SANITIZE_ADDRESS | 224 NO_SANITIZE_ADDRESS |
| 225 static bool shouldTracePersistentNode(Visitor*, PersistentNode*); | 225 static bool shouldTracePersistentNode(Visitor*, PersistentNode*); |
| 226 | 226 |
| 227 #if defined(ADDRESS_SANITIZER) |
| 228 void unpoisonCrossThreadPersistents(); |
| 229 #endif |
| 230 |
| 227 private: | 231 private: |
| 228 friend class LockScope; | 232 friend class LockScope; |
| 229 | 233 |
| 230 void lock() { m_mutex.lock(); } | 234 void lock() { m_mutex.lock(); } |
| 231 | 235 |
| 232 void unlock() { m_mutex.unlock(); } | 236 void unlock() { m_mutex.unlock(); } |
| 233 | 237 |
| 234 // We don't make CrossThreadPersistentRegion inherit from PersistentRegion | 238 // We don't make CrossThreadPersistentRegion inherit from PersistentRegion |
| 235 // because we don't want to virtualize performance-sensitive methods | 239 // because we don't want to virtualize performance-sensitive methods |
| 236 // such as PersistentRegion::allocate/freePersistentNode. | 240 // such as PersistentRegion::allocate/freePersistentNode. |
| 237 std::unique_ptr<PersistentRegion> m_persistentRegion; | 241 std::unique_ptr<PersistentRegion> m_persistentRegion; |
| 238 | 242 |
| 239 // Recursive as prepareForThreadStateTermination() clears a PersistentNode's | 243 // Recursive as prepareForThreadStateTermination() clears a PersistentNode's |
| 240 // associated Persistent<> -- it in turn freeing the PersistentNode. And both | 244 // associated Persistent<> -- it in turn freeing the PersistentNode. And both |
| 241 // CrossThreadPersistentRegion operations need a lock on the region before | 245 // CrossThreadPersistentRegion operations need a lock on the region before |
| 242 // mutating. | 246 // mutating. |
| 243 RecursiveMutex m_mutex; | 247 RecursiveMutex m_mutex; |
| 244 }; | 248 }; |
| 245 | 249 |
| 246 } // namespace blink | 250 } // namespace blink |
| 247 | 251 |
| 248 #endif | 252 #endif |
| OLD | NEW |