| 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 #include "platform/heap/PersistentNode.h" | 5 #include "platform/heap/PersistentNode.h" |
| 6 | 6 |
| 7 #include "base/debug/alias.h" | 7 #include "base/debug/alias.h" |
| 8 #include "platform/heap/Handle.h" | 8 #include "platform/heap/Handle.h" |
| 9 | 9 |
| 10 namespace blink { | 10 namespace blink { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 } | 35 } |
| 36 } | 36 } |
| 37 #if DCHECK_IS_ON() | 37 #if DCHECK_IS_ON() |
| 38 DCHECK_EQ(persistentCount, m_persistentCount); | 38 DCHECK_EQ(persistentCount, m_persistentCount); |
| 39 #endif | 39 #endif |
| 40 return persistentCount; | 40 return persistentCount; |
| 41 } | 41 } |
| 42 | 42 |
| 43 void PersistentRegion::ensurePersistentNodeSlots(void* self, | 43 void PersistentRegion::ensurePersistentNodeSlots(void* self, |
| 44 TraceCallback trace) { | 44 TraceCallback trace) { |
| 45 ASSERT(!m_freeListHead); | 45 DCHECK(!m_freeListHead); |
| 46 PersistentNodeSlots* slots = new PersistentNodeSlots; | 46 PersistentNodeSlots* slots = new PersistentNodeSlots; |
| 47 for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { | 47 for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { |
| 48 PersistentNode* node = &slots->m_slot[i]; | 48 PersistentNode* node = &slots->m_slot[i]; |
| 49 node->setFreeListNext(m_freeListHead); | 49 node->setFreeListNext(m_freeListHead); |
| 50 m_freeListHead = node; | 50 m_freeListHead = node; |
| 51 ASSERT(node->isUnused()); | 51 DCHECK(node->isUnused()); |
| 52 } | 52 } |
| 53 slots->m_next = m_slots; | 53 slots->m_next = m_slots; |
| 54 m_slots = slots; | 54 m_slots = slots; |
| 55 } | 55 } |
| 56 | 56 |
| 57 void PersistentRegion::releasePersistentNode( | 57 void PersistentRegion::releasePersistentNode( |
| 58 PersistentNode* persistentNode, | 58 PersistentNode* persistentNode, |
| 59 ThreadState::PersistentClearCallback callback) { | 59 ThreadState::PersistentClearCallback callback) { |
| 60 ASSERT(!persistentNode->isUnused()); | 60 DCHECK(!persistentNode->isUnused()); |
| 61 // 'self' is in use, containing the persistent wrapper object. | 61 // 'self' is in use, containing the persistent wrapper object. |
| 62 void* self = persistentNode->self(); | 62 void* self = persistentNode->self(); |
| 63 if (callback) { | 63 if (callback) { |
| 64 (*callback)(self); | 64 (*callback)(self); |
| 65 ASSERT(persistentNode->isUnused()); | 65 DCHECK(persistentNode->isUnused()); |
| 66 return; | 66 return; |
| 67 } | 67 } |
| 68 Persistent<DummyGCBase>* persistent = | 68 Persistent<DummyGCBase>* persistent = |
| 69 reinterpret_cast<Persistent<DummyGCBase>*>(self); | 69 reinterpret_cast<Persistent<DummyGCBase>*>(self); |
| 70 persistent->clear(); | 70 persistent->clear(); |
| 71 ASSERT(persistentNode->isUnused()); | 71 DCHECK(persistentNode->isUnused()); |
| 72 } | 72 } |
| 73 | 73 |
| 74 // This function traces all PersistentNodes. If we encounter | 74 // This function traces all PersistentNodes. If we encounter |
| 75 // a PersistentNodeSlot that contains only freed PersistentNodes, | 75 // a PersistentNodeSlot that contains only freed PersistentNodes, |
| 76 // we delete the PersistentNodeSlot. This function rebuilds the free | 76 // we delete the PersistentNodeSlot. This function rebuilds the free |
| 77 // list of PersistentNodes. | 77 // list of PersistentNodes. |
| 78 void PersistentRegion::tracePersistentNodes(Visitor* visitor, | 78 void PersistentRegion::tracePersistentNodes(Visitor* visitor, |
| 79 ShouldTraceCallback shouldTrace) { | 79 ShouldTraceCallback shouldTrace) { |
| 80 size_t debugMarkedObjectSize = ProcessHeap::totalMarkedObjectSize(); | 80 size_t debugMarkedObjectSize = ProcessHeap::totalMarkedObjectSize(); |
| 81 base::debug::Alias(&debugMarkedObjectSize); | 81 base::debug::Alias(&debugMarkedObjectSize); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 104 debugMarkedObjectSize = ProcessHeap::totalMarkedObjectSize(); | 104 debugMarkedObjectSize = ProcessHeap::totalMarkedObjectSize(); |
| 105 } | 105 } |
| 106 } | 106 } |
| 107 if (freeCount == PersistentNodeSlots::slotCount) { | 107 if (freeCount == PersistentNodeSlots::slotCount) { |
| 108 PersistentNodeSlots* deadSlots = slots; | 108 PersistentNodeSlots* deadSlots = slots; |
| 109 *prevNext = slots->m_next; | 109 *prevNext = slots->m_next; |
| 110 slots = slots->m_next; | 110 slots = slots->m_next; |
| 111 delete deadSlots; | 111 delete deadSlots; |
| 112 } else { | 112 } else { |
| 113 if (freeListLast) { | 113 if (freeListLast) { |
| 114 ASSERT(freeListNext); | 114 DCHECK(freeListNext); |
| 115 ASSERT(!freeListLast->freeListNext()); | 115 DCHECK(!freeListLast->freeListNext()); |
| 116 freeListLast->setFreeListNext(m_freeListHead); | 116 freeListLast->setFreeListNext(m_freeListHead); |
| 117 m_freeListHead = freeListNext; | 117 m_freeListHead = freeListNext; |
| 118 } | 118 } |
| 119 prevNext = &slots->m_next; | 119 prevNext = &slots->m_next; |
| 120 slots = slots->m_next; | 120 slots = slots->m_next; |
| 121 } | 121 } |
| 122 } | 122 } |
| 123 #if DCHECK_IS_ON() | 123 #if DCHECK_IS_ON() |
| 124 DCHECK_EQ(persistentCount, m_persistentCount); | 124 DCHECK_EQ(persistentCount, m_persistentCount); |
| 125 #endif | 125 #endif |
| (...skipping 26 matching lines...) Expand all Loading... |
| 152 while (slots) { | 152 while (slots) { |
| 153 for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { | 153 for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { |
| 154 if (slots->m_slot[i].isUnused()) | 154 if (slots->m_slot[i].isUnused()) |
| 155 continue; | 155 continue; |
| 156 | 156 |
| 157 // 'self' is in use, containing the cross-thread persistent wrapper | 157 // 'self' is in use, containing the cross-thread persistent wrapper |
| 158 // object. | 158 // object. |
| 159 CrossThreadPersistent<DummyGCBase>* persistent = | 159 CrossThreadPersistent<DummyGCBase>* persistent = |
| 160 reinterpret_cast<CrossThreadPersistent<DummyGCBase>*>( | 160 reinterpret_cast<CrossThreadPersistent<DummyGCBase>*>( |
| 161 slots->m_slot[i].self()); | 161 slots->m_slot[i].self()); |
| 162 ASSERT(persistent); | 162 DCHECK(persistent); |
| 163 void* rawObject = persistent->atomicGet(); | 163 void* rawObject = persistent->atomicGet(); |
| 164 if (!rawObject) | 164 if (!rawObject) |
| 165 continue; | 165 continue; |
| 166 BasePage* page = pageFromObject(rawObject); | 166 BasePage* page = pageFromObject(rawObject); |
| 167 ASSERT(page); | 167 DCHECK(page); |
| 168 // The main thread will upon detach just mark its heap pages as orphaned, | 168 // The main thread will upon detach just mark its heap pages as orphaned, |
| 169 // but not invalidate its CrossThreadPersistent<>s. | 169 // but not invalidate its CrossThreadPersistent<>s. |
| 170 if (page->orphaned()) | 170 if (page->orphaned()) |
| 171 continue; | 171 continue; |
| 172 if (page->arena()->getThreadState() == threadState) { | 172 if (page->arena()->getThreadState() == threadState) { |
| 173 persistent->clear(); | 173 persistent->clear(); |
| 174 ASSERT(slots->m_slot[i].isUnused()); | 174 DCHECK(slots->m_slot[i].isUnused()); |
| 175 } | 175 } |
| 176 } | 176 } |
| 177 slots = slots->m_next; | 177 slots = slots->m_next; |
| 178 } | 178 } |
| 179 } | 179 } |
| 180 | 180 |
| 181 #if defined(ADDRESS_SANITIZER) | 181 #if defined(ADDRESS_SANITIZER) |
| 182 void CrossThreadPersistentRegion::unpoisonCrossThreadPersistents() { | 182 void CrossThreadPersistentRegion::unpoisonCrossThreadPersistents() { |
| 183 MutexLocker lock(m_mutex); | 183 MutexLocker lock(m_mutex); |
| 184 int persistentCount = 0; | 184 int persistentCount = 0; |
| 185 for (PersistentNodeSlots* slots = m_persistentRegion->m_slots; slots; | 185 for (PersistentNodeSlots* slots = m_persistentRegion->m_slots; slots; |
| 186 slots = slots->m_next) { | 186 slots = slots->m_next) { |
| 187 for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { | 187 for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { |
| 188 const PersistentNode& node = slots->m_slot[i]; | 188 const PersistentNode& node = slots->m_slot[i]; |
| 189 if (!node.isUnused()) { | 189 if (!node.isUnused()) { |
| 190 ASAN_UNPOISON_MEMORY_REGION(node.self(), | 190 ASAN_UNPOISON_MEMORY_REGION(node.self(), |
| 191 sizeof(CrossThreadPersistent<void*>)); | 191 sizeof(CrossThreadPersistent<void*>)); |
| 192 ++persistentCount; | 192 ++persistentCount; |
| 193 } | 193 } |
| 194 } | 194 } |
| 195 } | 195 } |
| 196 #if DCHECK_IS_ON() | 196 #if DCHECK_IS_ON() |
| 197 DCHECK_EQ(persistentCount, m_persistentRegion->m_persistentCount); | 197 DCHECK_EQ(persistentCount, m_persistentRegion->m_persistentCount); |
| 198 #endif | 198 #endif |
| 199 } | 199 } |
| 200 #endif | 200 #endif |
| 201 | 201 |
| 202 } // namespace blink | 202 } // namespace blink |
| OLD | NEW |