OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/CallbackStack.h" | 6 #include "platform/heap/CallbackStack.h" |
7 | 7 |
8 #include "platform/heap/Heap.h" | |
9 | |
10 namespace blink { | 8 namespace blink { |
11 | 9 |
12 void CallbackStack::Block::clear() | 10 void CallbackStack::Block::clear() |
13 { | 11 { |
14 m_current = &m_buffer[0]; | 12 m_current = &m_buffer[0]; |
15 m_next = 0; | 13 m_next = nullptr; |
16 clearUnused(); | 14 clearUnused(); |
17 } | 15 } |
18 | 16 |
19 void CallbackStack::Block::invokeEphemeronCallbacks(Visitor* visitor) | 17 void CallbackStack::Block::invokeEphemeronCallbacks(Visitor* visitor) |
20 { | 18 { |
21 // This loop can tolerate entries being added by the callbacks after | 19 // This loop can tolerate entries being added by the callbacks after |
22 // iteration starts. | 20 // iteration starts. |
23 for (unsigned i = 0; m_buffer + i < m_current; i++) { | 21 for (unsigned i = 0; m_buffer + i < m_current; i++) { |
24 Item& item = m_buffer[i]; | 22 Item& item = m_buffer[i]; |
25 item.call(visitor); | 23 item.call(visitor); |
(...skipping 21 matching lines...) Expand all Loading... |
47 } | 45 } |
48 | 46 |
49 CallbackStack::CallbackStack() : m_first(new Block(0)), m_last(m_first) | 47 CallbackStack::CallbackStack() : m_first(new Block(0)), m_last(m_first) |
50 { | 48 { |
51 } | 49 } |
52 | 50 |
53 CallbackStack::~CallbackStack() | 51 CallbackStack::~CallbackStack() |
54 { | 52 { |
55 clear(); | 53 clear(); |
56 delete m_first; | 54 delete m_first; |
57 m_first = 0; | 55 m_first = nullptr; |
58 m_last = 0; | 56 m_last = nullptr; |
59 } | 57 } |
60 | 58 |
61 void CallbackStack::clear() | 59 void CallbackStack::clear() |
62 { | 60 { |
63 Block* next; | 61 Block* next; |
64 for (Block* current = m_first->next(); current; current = next) { | 62 for (Block* current = m_first->next(); current; current = next) { |
65 next = current->next(); | 63 next = current->next(); |
66 delete current; | 64 delete current; |
67 } | 65 } |
68 m_first->clear(); | 66 m_first->clear(); |
(...skipping 10 matching lines...) Expand all Loading... |
79 ASSERT(!m_first->allocateEntry()); | 77 ASSERT(!m_first->allocateEntry()); |
80 m_first = new Block(m_first); | 78 m_first = new Block(m_first); |
81 return m_first->allocateEntry(); | 79 return m_first->allocateEntry(); |
82 } | 80 } |
83 | 81 |
84 CallbackStack::Item* CallbackStack::popSlow() | 82 CallbackStack::Item* CallbackStack::popSlow() |
85 { | 83 { |
86 ASSERT(m_first->isEmptyBlock()); | 84 ASSERT(m_first->isEmptyBlock()); |
87 | 85 |
88 for (;;) { | 86 for (;;) { |
89 if (hasJustOneBlock()) { | 87 Block* next = m_first->next(); |
| 88 if (!next) { |
90 #if ENABLE(ASSERT) | 89 #if ENABLE(ASSERT) |
91 m_first->clear(); | 90 m_first->clear(); |
92 #endif | 91 #endif |
93 return 0; | 92 return nullptr; |
94 } | 93 } |
95 Block* next = m_first->next(); | |
96 delete m_first; | 94 delete m_first; |
97 m_first = next; | 95 m_first = next; |
98 if (Item* item = m_first->pop()) | 96 if (Item* item = m_first->pop()) |
99 return item; | 97 return item; |
100 } | 98 } |
101 } | 99 } |
102 | 100 |
103 void CallbackStack::invokeEphemeronCallbacks(Visitor* visitor) | 101 void CallbackStack::invokeEphemeronCallbacks(Visitor* visitor) |
104 { | 102 { |
105 // The first block is the only one where new ephemerons are added, so we | 103 // The first block is the only one where new ephemerons are added, so we |
106 // call the callbacks on that last, to catch any new ephemerons discovered | 104 // call the callbacks on that last, to catch any new ephemerons discovered |
107 // in the callbacks. | 105 // in the callbacks. |
108 // However, if enough ephemerons were added, we may have a new block that | 106 // However, if enough ephemerons were added, we may have a new block that |
109 // has been prepended to the chain. This will be very rare, but we can | 107 // has been prepended to the chain. This will be very rare, but we can |
110 // handle the situation by starting again and calling all the callbacks | 108 // handle the situation by starting again and calling all the callbacks |
111 // on the prepended blocks. | 109 // on the prepended blocks. |
112 Block* from = 0; | 110 Block* from = nullptr; |
113 Block* upto = 0; | 111 Block* upto = nullptr; |
114 while (from != m_first) { | 112 while (from != m_first) { |
115 upto = from; | 113 upto = from; |
116 from = m_first; | 114 from = m_first; |
117 invokeOldestCallbacks(from, upto, visitor); | 115 invokeOldestCallbacks(from, upto, visitor); |
118 } | 116 } |
119 } | 117 } |
120 | 118 |
121 void CallbackStack::invokeOldestCallbacks(Block* from, Block* upto, Visitor* vis
itor) | 119 void CallbackStack::invokeOldestCallbacks(Block* from, Block* upto, Visitor* vis
itor) |
122 { | 120 { |
123 if (from == upto) | 121 if (from == upto) |
124 return; | 122 return; |
125 ASSERT(from); | 123 ASSERT(from); |
126 // Recurse first (blockSize at a time) so we get to the newly added entries
last. | 124 // Recurse first (blockSize at a time) so we get to the newly added entries
last. |
127 invokeOldestCallbacks(from->next(), upto, visitor); | 125 invokeOldestCallbacks(from->next(), upto, visitor); |
128 from->invokeEphemeronCallbacks(visitor); | 126 from->invokeEphemeronCallbacks(visitor); |
129 } | 127 } |
130 | 128 |
131 bool CallbackStack::hasJustOneBlock() const | 129 bool CallbackStack::hasJustOneBlock() const |
132 { | 130 { |
133 return !m_first->next(); | 131 return !m_first->next(); |
134 } | 132 } |
135 | 133 |
136 void CallbackStack::swap(CallbackStack* other) | |
137 { | |
138 Block* tmp = m_first; | |
139 m_first = other->m_first; | |
140 other->m_first = tmp; | |
141 tmp = m_last; | |
142 m_last = other->m_last; | |
143 other->m_last = tmp; | |
144 } | |
145 | |
146 #if ENABLE(ASSERT) | 134 #if ENABLE(ASSERT) |
147 bool CallbackStack::hasCallbackForObject(const void* object) | 135 bool CallbackStack::hasCallbackForObject(const void* object) |
148 { | 136 { |
149 for (Block* current = m_first; current; current = current->next()) { | 137 for (Block* current = m_first; current; current = current->next()) { |
150 if (current->hasCallbackForObject(object)) | 138 if (current->hasCallbackForObject(object)) |
151 return true; | 139 return true; |
152 } | 140 } |
153 return false; | 141 return false; |
154 } | 142 } |
155 #endif | 143 #endif |
156 | 144 |
157 } | 145 } |
OLD | NEW |