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 "platform/heap/CallbackStack.h" | 5 #include "platform/heap/CallbackStack.h" |
| 6 #include "wtf/PageAllocator.h" |
6 | 7 |
7 namespace blink { | 8 namespace blink { |
8 | 9 |
| 10 CallbackStack::Block::Block(Block* next) |
| 11 { |
| 12 static_assert((blockSize * sizeof(Item)) % WTF::kPageAllocationGranularity =
= 0, "CallbackStack::blockSize * sizeof(Item) must be a multiple of WTF::kPageAl
locationGranularity"); |
| 13 m_buffer = static_cast<Item*>(WTF::allocPages(nullptr, blockSize * sizeof(It
em), WTF::kPageAllocationGranularity, WTF::PageAccessible)); |
| 14 RELEASE_ASSERT(m_buffer); |
| 15 |
| 16 #if ENABLE(ASSERT) |
| 17 clear(); |
| 18 #endif |
| 19 |
| 20 m_limit = &(m_buffer[blockSize]); |
| 21 m_current = &(m_buffer[0]); |
| 22 m_next = next; |
| 23 } |
| 24 |
| 25 CallbackStack::Block::~Block() |
| 26 { |
| 27 WTF::freePages(m_buffer, blockSize * sizeof(Item)); |
| 28 m_buffer = nullptr; |
| 29 m_limit = nullptr; |
| 30 m_current = nullptr; |
| 31 m_next = nullptr; |
| 32 } |
| 33 |
| 34 #if ENABLE(ASSERT) |
9 void CallbackStack::Block::clear() | 35 void CallbackStack::Block::clear() |
10 { | 36 { |
| 37 for (size_t i = 0; i < blockSize; i++) |
| 38 m_buffer[i] = Item(0, 0); |
| 39 } |
| 40 #endif |
| 41 |
| 42 void CallbackStack::Block::decommit() |
| 43 { |
| 44 #if ENABLE(ASSERT) |
| 45 clear(); |
| 46 #endif |
| 47 WTF::discardSystemPages(m_buffer, blockSize * sizeof(Item)); |
| 48 |
11 m_current = &m_buffer[0]; | 49 m_current = &m_buffer[0]; |
12 m_next = nullptr; | 50 m_next = nullptr; |
13 clearUnused(); | |
14 } | 51 } |
15 | 52 |
16 void CallbackStack::Block::invokeEphemeronCallbacks(Visitor* visitor) | 53 void CallbackStack::Block::invokeEphemeronCallbacks(Visitor* visitor) |
17 { | 54 { |
18 // This loop can tolerate entries being added by the callbacks after | 55 // This loop can tolerate entries being added by the callbacks after |
19 // iteration starts. | 56 // iteration starts. |
20 for (unsigned i = 0; m_buffer + i < m_current; i++) { | 57 for (unsigned i = 0; m_buffer + i < m_current; i++) { |
21 Item& item = m_buffer[i]; | 58 Item& item = m_buffer[i]; |
22 item.call(visitor); | 59 item.call(visitor); |
23 } | 60 } |
24 } | 61 } |
25 | 62 |
26 #if ENABLE(ASSERT) | 63 #if ENABLE(ASSERT) |
27 bool CallbackStack::Block::hasCallbackForObject(const void* object) | 64 bool CallbackStack::Block::hasCallbackForObject(const void* object) |
28 { | 65 { |
29 for (unsigned i = 0; m_buffer + i < m_current; i++) { | 66 for (unsigned i = 0; m_buffer + i < m_current; i++) { |
30 Item* item = &m_buffer[i]; | 67 Item* item = &m_buffer[i]; |
31 if (item->object() == object) | 68 if (item->object() == object) |
32 return true; | 69 return true; |
33 } | 70 } |
34 return false; | 71 return false; |
35 } | 72 } |
36 #endif | 73 #endif |
37 | 74 |
38 void CallbackStack::Block::clearUnused() | 75 CallbackStack::CallbackStack() |
39 { | 76 : m_first(new Block(0)) |
40 #if ENABLE(ASSERT) | 77 , m_last(m_first) |
41 for (size_t i = 0; i < blockSize; i++) | |
42 m_buffer[i] = Item(0, 0); | |
43 #endif | |
44 } | |
45 | |
46 CallbackStack::CallbackStack() : m_first(new Block(0)), m_last(m_first) | |
47 { | 78 { |
48 } | 79 } |
49 | 80 |
50 CallbackStack::~CallbackStack() | 81 CallbackStack::~CallbackStack() |
51 { | 82 { |
52 clear(); | 83 RELEASE_ASSERT(isEmpty()); |
53 delete m_first; | 84 delete m_first; |
54 m_first = nullptr; | 85 m_first = nullptr; |
55 m_last = nullptr; | 86 m_last = nullptr; |
56 } | 87 } |
57 | 88 |
58 void CallbackStack::clear() | 89 void CallbackStack::decommit() |
59 { | 90 { |
60 Block* next; | 91 Block* next; |
61 for (Block* current = m_first->next(); current; current = next) { | 92 for (Block* current = m_first->next(); current; current = next) { |
62 next = current->next(); | 93 next = current->next(); |
63 delete current; | 94 delete current; |
64 } | 95 } |
65 m_first->clear(); | 96 m_first->decommit(); |
66 m_last = m_first; | 97 m_last = m_first; |
67 } | 98 } |
68 | 99 |
69 bool CallbackStack::isEmpty() const | 100 bool CallbackStack::isEmpty() const |
70 { | 101 { |
71 return hasJustOneBlock() && m_first->isEmptyBlock(); | 102 return hasJustOneBlock() && m_first->isEmptyBlock(); |
72 } | 103 } |
73 | 104 |
74 CallbackStack::Item* CallbackStack::allocateEntrySlow() | 105 CallbackStack::Item* CallbackStack::allocateEntrySlow() |
75 { | 106 { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 { | 166 { |
136 for (Block* current = m_first; current; current = current->next()) { | 167 for (Block* current = m_first; current; current = current->next()) { |
137 if (current->hasCallbackForObject(object)) | 168 if (current->hasCallbackForObject(object)) |
138 return true; | 169 return true; |
139 } | 170 } |
140 return false; | 171 return false; |
141 } | 172 } |
142 #endif | 173 #endif |
143 | 174 |
144 } // namespace blink | 175 } // namespace blink |
OLD | NEW |