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 |
9 void CallbackStack::Block::clear() | 10 CallbackStack::Block::Block(Block* next) |
10 { | 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 for (size_t i = 0; i < blockSize; i++) | |
18 m_buffer[i] = Item(0, 0); | |
19 #endif | |
20 | |
21 m_limit = &(m_buffer[blockSize]); | |
22 m_current = &(m_buffer[0]); | |
23 m_next = next; | |
24 } | |
25 | |
26 CallbackStack::Block::~Block() | |
27 { | |
28 WTF::freePages(m_buffer, blockSize * sizeof(Item)); | |
29 m_buffer = nullptr; | |
30 m_limit = nullptr; | |
31 m_current = nullptr; | |
32 m_next = nullptr; | |
33 } | |
34 | |
35 void CallbackStack::Block::decommit() | |
36 { | |
37 #if ENABLE(ASSERT) | |
38 for (size_t i = 0; i < blockSize; i++) | |
39 m_buffer[i] = Item(0, 0); | |
40 #endif | |
41 | |
42 WTF::discardSystemPages(m_buffer, blockSize * sizeof(Item)); | |
43 | |
11 m_current = &m_buffer[0]; | 44 m_current = &m_buffer[0]; |
12 m_next = nullptr; | 45 m_next = nullptr; |
13 clearUnused(); | |
14 } | 46 } |
15 | 47 |
16 void CallbackStack::Block::invokeEphemeronCallbacks(Visitor* visitor) | 48 void CallbackStack::Block::invokeEphemeronCallbacks(Visitor* visitor) |
17 { | 49 { |
18 // This loop can tolerate entries being added by the callbacks after | 50 // This loop can tolerate entries being added by the callbacks after |
19 // iteration starts. | 51 // iteration starts. |
20 for (unsigned i = 0; m_buffer + i < m_current; i++) { | 52 for (unsigned i = 0; m_buffer + i < m_current; i++) { |
21 Item& item = m_buffer[i]; | 53 Item& item = m_buffer[i]; |
22 item.call(visitor); | 54 item.call(visitor); |
23 } | 55 } |
24 } | 56 } |
25 | 57 |
26 #if ENABLE(ASSERT) | 58 #if ENABLE(ASSERT) |
27 bool CallbackStack::Block::hasCallbackForObject(const void* object) | 59 bool CallbackStack::Block::hasCallbackForObject(const void* object) |
28 { | 60 { |
29 for (unsigned i = 0; m_buffer + i < m_current; i++) { | 61 for (unsigned i = 0; m_buffer + i < m_current; i++) { |
30 Item* item = &m_buffer[i]; | 62 Item* item = &m_buffer[i]; |
31 if (item->object() == object) | 63 if (item->object() == object) |
32 return true; | 64 return true; |
33 } | 65 } |
34 return false; | 66 return false; |
35 } | 67 } |
36 #endif | 68 #endif |
37 | 69 |
38 void CallbackStack::Block::clearUnused() | 70 CallbackStack::CallbackStack() |
39 { | 71 : m_first(new Block(0)) |
40 #if ENABLE(ASSERT) | 72 , 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 { | 73 { |
48 } | 74 } |
49 | 75 |
50 CallbackStack::~CallbackStack() | 76 CallbackStack::~CallbackStack() |
51 { | 77 { |
52 clear(); | 78 RELEASE_ASSERT(isEmpty()); |
53 delete m_first; | 79 delete m_first; |
54 m_first = nullptr; | 80 m_first = nullptr; |
55 m_last = nullptr; | 81 m_last = nullptr; |
56 } | 82 } |
57 | 83 |
58 void CallbackStack::clear() | 84 void CallbackStack::decommit() |
59 { | 85 { |
60 Block* next; | 86 Block* next; |
61 for (Block* current = m_first->next(); current; current = next) { | 87 for (Block* current = m_first->next(); current; current = next) { |
62 next = current->next(); | 88 next = current->next(); |
63 delete current; | 89 delete current; |
64 } | 90 } |
65 m_first->clear(); | 91 m_first->decommit(); |
66 m_last = m_first; | 92 m_last = m_first; |
67 } | 93 } |
68 | 94 |
69 bool CallbackStack::isEmpty() const | 95 bool CallbackStack::isEmpty() const |
70 { | 96 { |
71 return hasJustOneBlock() && m_first->isEmptyBlock(); | 97 return hasJustOneBlock() && m_first->isEmptyBlock(); |
72 } | 98 } |
73 | 99 |
74 CallbackStack::Item* CallbackStack::allocateEntrySlow() | 100 CallbackStack::Item* CallbackStack::allocateEntrySlow() |
75 { | 101 { |
76 ASSERT(!m_first->allocateEntry()); | 102 ASSERT(!m_first->allocateEntry()); |
77 m_first = new Block(m_first); | 103 m_first = new Block(m_first); |
78 return m_first->allocateEntry(); | 104 return m_first->allocateEntry(); |
79 } | 105 } |
80 | 106 |
81 CallbackStack::Item* CallbackStack::popSlow() | 107 CallbackStack::Item* CallbackStack::popSlow() |
82 { | 108 { |
83 ASSERT(m_first->isEmptyBlock()); | 109 ASSERT(m_first->isEmptyBlock()); |
84 | 110 |
85 for (;;) { | 111 for (;;) { |
86 Block* next = m_first->next(); | 112 Block* next = m_first->next(); |
87 if (!next) { | 113 if (!next) { |
88 #if ENABLE(ASSERT) | 114 #if ENABLE(ASSERT) |
89 m_first->clear(); | 115 m_first->decommit(); |
sof
2016/02/24 09:50:05
Isn't this call redundant/unwanted if the stack it
haraken
2016/02/24 10:06:19
This decommit is only enabled in assert builds whe
sof
2016/02/24 10:07:39
Shouldn't it just do the clearing then?
haraken
2016/02/24 10:21:44
Done.
sof
2016/02/24 10:32:23
Not yet uploaded?
| |
90 #endif | 116 #endif |
91 return nullptr; | 117 return nullptr; |
92 } | 118 } |
93 delete m_first; | 119 delete m_first; |
94 m_first = next; | 120 m_first = next; |
95 if (Item* item = m_first->pop()) | 121 if (Item* item = m_first->pop()) |
96 return item; | 122 return item; |
97 } | 123 } |
98 } | 124 } |
99 | 125 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 { | 161 { |
136 for (Block* current = m_first; current; current = current->next()) { | 162 for (Block* current = m_first; current; current = current->next()) { |
137 if (current->hasCallbackForObject(object)) | 163 if (current->hasCallbackForObject(object)) |
138 return true; | 164 return true; |
139 } | 165 } |
140 return false; | 166 return false; |
141 } | 167 } |
142 #endif | 168 #endif |
143 | 169 |
144 } // namespace blink | 170 } // namespace blink |
OLD | NEW |