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 "config.h" | 5 #include "config.h" |
6 #include "platform/heap/PersistentNode.h" | 6 #include "platform/heap/PersistentNode.h" |
7 | 7 |
8 #include "platform/heap/Handle.h" | |
9 | |
8 namespace blink { | 10 namespace blink { |
9 | 11 |
10 PersistentRegion::~PersistentRegion() | 12 PersistentRegion::~PersistentRegion() |
11 { | 13 { |
12 PersistentNodeSlots* slots = m_slots; | 14 PersistentNodeSlots* slots = m_slots; |
13 while (slots) { | 15 while (slots) { |
14 PersistentNodeSlots* deadSlots = slots; | 16 PersistentNodeSlots* deadSlots = slots; |
15 slots = slots->m_next; | 17 slots = slots->m_next; |
16 delete deadSlots; | 18 delete deadSlots; |
17 } | 19 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
53 m_freeListHead = nullptr; | 55 m_freeListHead = nullptr; |
54 int persistentCount = 0; | 56 int persistentCount = 0; |
55 PersistentNodeSlots** prevNext = &m_slots; | 57 PersistentNodeSlots** prevNext = &m_slots; |
56 PersistentNodeSlots* slots = m_slots; | 58 PersistentNodeSlots* slots = m_slots; |
57 while (slots) { | 59 while (slots) { |
58 PersistentNode* freeListNext = nullptr; | 60 PersistentNode* freeListNext = nullptr; |
59 PersistentNode* freeListLast = nullptr; | 61 PersistentNode* freeListLast = nullptr; |
60 int freeCount = 0; | 62 int freeCount = 0; |
61 for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { | 63 for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { |
62 PersistentNode* node = &slots->m_slot[i]; | 64 PersistentNode* node = &slots->m_slot[i]; |
65 if (!node->isValid()) { | |
66 // We do allow CrossThreadPersistent<> handles to exist beyond | |
67 // the lifetime of the object they refer to and keep alive. | |
68 // This to allow an Oilpan thread to shut down and terminate | |
haraken
2015/08/03 00:45:25
This is to allow
| |
69 // without first coordinating with any and all threads that hold | |
70 // CrossThreadPersistent<>s pointing into its heaps - to have | |
71 // them first release those references - before the thread | |
72 // proceeds to detach its heaps and shuts down. | |
73 // | |
74 // The cross-thread persistent variant eases the same-thread | |
75 // destruction restriction of a persistent (while also keeping | |
76 // the object it refers to alive). The persistent reference isn' t | |
77 // however so strong so as to prevent a heap being detached and | |
78 // destructed. Just that the destruction of the cross-thread | |
79 // persistent may happen later and independently from the | |
80 // heap of the object it points to. | |
81 // | |
82 // It is clearly not safe to continue tracing cross-thread | |
83 // persistents referring to objects and heaps that have been | |
84 // destructed, so these will be marked as invalid and skipped he re. | |
85 ++persistentCount; | |
86 continue; | |
87 } | |
63 if (node->isUnused()) { | 88 if (node->isUnused()) { |
64 if (!freeListNext) | 89 if (!freeListNext) |
65 freeListLast = node; | 90 freeListLast = node; |
66 node->setFreeListNext(freeListNext); | 91 node->setFreeListNext(freeListNext); |
67 freeListNext = node; | 92 freeListNext = node; |
68 ++freeCount; | 93 ++freeCount; |
69 } else { | 94 } else { |
70 node->tracePersistentNode(visitor); | 95 node->tracePersistentNode(visitor); |
71 ++persistentCount; | 96 ++persistentCount; |
72 } | 97 } |
(...skipping 10 matching lines...) Expand all Loading... | |
83 freeListLast->setFreeListNext(m_freeListHead); | 108 freeListLast->setFreeListNext(m_freeListHead); |
84 m_freeListHead = freeListNext; | 109 m_freeListHead = freeListNext; |
85 } | 110 } |
86 prevNext = &slots->m_next; | 111 prevNext = &slots->m_next; |
87 slots = slots->m_next; | 112 slots = slots->m_next; |
88 } | 113 } |
89 } | 114 } |
90 ASSERT(persistentCount == m_persistentCount); | 115 ASSERT(persistentCount == m_persistentCount); |
91 } | 116 } |
92 | 117 |
118 void CrossThreadPersistentRegion::prepareForThreadStateTermination(ThreadState* threadState) | |
119 { | |
120 // For heaps belonging to a thread that's detaching, any cross-thread persis tents | |
121 // pointing into them needs to be disabled. | |
122 MutexLocker lock(m_mutex); | |
123 | |
124 class Object; | |
125 using GCObject = GarbageCollected<Object>; | |
126 | |
127 // TODO(sof): consider ways of reducing the overhead of this invalidation. | |
128 // (e.g., tracking number of active CrossThreadPersistent<>s pointing | |
129 // into the heaps of each ThreadState & use that count to terminate traversa l.) | |
haraken
2015/08/03 00:45:25
Given that the number of CrossThreadPersistents sh
sof
2015/08/03 08:30:04
I'd like to revisit and address, but thread local
| |
130 PersistentNodeSlots* slots = m_persistentRegion->m_slots; | |
131 while (slots) { | |
132 for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { | |
133 if (!slots->m_slot[i].isValid() || slots->m_slot[i].isUnused()) | |
134 continue; | |
135 | |
136 // 'self' is in use, containing the cross-thread persistent wrapper object. | |
137 CrossThreadPersistent<GCObject>* persistent = reinterpret_cast<Cross ThreadPersistent<GCObject>*>(slots->m_slot[i].self()); | |
138 ASSERT(persistent); | |
139 void* rawObject = persistent->get(); | |
140 if (!rawObject) | |
141 continue; | |
142 BasePage* page = pageFromObject(rawObject); | |
143 ASSERT(page); | |
144 if (page->heap()->threadState() == threadState) | |
145 slots->m_slot[i].invalidate(); | |
146 } | |
147 slots = slots->m_next; | |
148 } | |
149 } | |
150 | |
93 } // namespace blink | 151 } // namespace blink |
OLD | NEW |