Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: third_party/WebKit/Source/platform/heap/CallbackStack.cpp

Issue 2127453002: Oilpan: Introduce memory pool for CallbackStacks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: temp Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/PtrUtil.h"
6 #include "wtf/allocator/PageAllocator.h" 7 #include "wtf/allocator/PageAllocator.h"
8 #include "wtf/allocator/Partitions.h"
7 9
8 namespace blink { 10 namespace blink {
9 11
10 size_t const CallbackStack::kMinimalBlockSize = WTF::kPageAllocationGranularity / sizeof(CallbackStack::Item); 12 CallbackStackMemoryPool& CallbackStackMemoryPool::instance()
13 {
14 DEFINE_STATIC_LOCAL(CallbackStackMemoryPool, memoryPool, ());
15 return memoryPool;
16 }
11 17
12 CallbackStack::Block::Block(Block* next, size_t blockSize) 18 void CallbackStackMemoryPool::initialize()
13 : m_blockSize(blockSize)
14 { 19 {
15 // Allocated block size must be a multiple of WTF::kPageAllocationGranularit y. 20 m_freeListFirst = 0;
16 ASSERT((m_blockSize * sizeof(Item)) % WTF::kPageAllocationGranularity == 0); 21 for (size_t index = 0; index < kPooledBlockCount - 1; ++index) {
17 m_buffer = static_cast<Item*>(WTF::allocPages(nullptr, m_blockSize * sizeof( Item), WTF::kPageAllocationGranularity, WTF::PageAccessible)); 22 m_freeListNext[index] = index + 1;
18 RELEASE_ASSERT(m_buffer); 23 }
24 m_freeListNext[kPooledBlockCount - 1] = -1;
25 m_pooledMemory = static_cast<CallbackStack::Item*>(WTF::allocPages(nullptr, kBlockBytes * kPooledBlockCount, WTF::kPageAllocationGranularity, WTF::PageAcces sible));
26 CHECK(m_pooledMemory);
27 }
19 28
29 void CallbackStackMemoryPool::shutdown()
30 {
31 WTF::freePages(m_pooledMemory, kBlockBytes * kPooledBlockCount);
32 m_pooledMemory = nullptr;
33 m_freeListFirst = 0;
34 }
35
36 CallbackStack::Item* CallbackStackMemoryPool::allocate()
37 {
38 MutexLocker locker(m_mutex);
39 // Allocate from a free list if available.
40 if (m_freeListFirst != -1) {
41 size_t index = m_freeListFirst;
42 DCHECK(0 <= index && index < CallbackStackMemoryPool::kPooledBlockCount) ;
43 m_freeListFirst = m_freeListNext[index];
44 m_freeListNext[index] = -1;
45 return m_pooledMemory + kBlockSize * index;
46 }
47 // Otherwise, allocate a new memory region.
48 CallbackStack::Item* memory = static_cast<CallbackStack::Item*>(WTF::Partiti ons::fastZeroedMalloc(kBlockBytes, "CallbackStackMemoryPool"));
49 CHECK(memory);
50 return memory;
51 }
52
53 void CallbackStackMemoryPool::free(CallbackStack::Item* memory)
54 {
55 MutexLocker locker(m_mutex);
56 int index = (reinterpret_cast<uintptr_t>(memory) - reinterpret_cast<uintptr_ t>(m_pooledMemory)) / (kBlockSize * sizeof(CallbackStack::Item));
57 // If the memory is a newly allocated region, free the memory.
58 if (index < 0 || static_cast<int>(kPooledBlockCount) <= index) {
59 WTF::Partitions::fastFree(memory);
60 return;
61 }
62 // Otherwise, return the memory back to the free list.
63 DCHECK_EQ(m_freeListNext[index], -1);
64 m_freeListNext[index] = m_freeListFirst;
65 m_freeListFirst = index;
66 }
67
68 CallbackStack::Block::Block(Block* next)
69 {
70 m_buffer = CallbackStackMemoryPool::instance().allocate();
20 #if ENABLE(ASSERT) 71 #if ENABLE(ASSERT)
21 clear(); 72 clear();
22 #endif 73 #endif
23 74
24 m_limit = &(m_buffer[m_blockSize]); 75 m_limit = &(m_buffer[CallbackStackMemoryPool::kBlockSize]);
25 m_current = &(m_buffer[0]); 76 m_current = &(m_buffer[0]);
26 m_next = next; 77 m_next = next;
27 } 78 }
28 79
29 CallbackStack::Block::~Block() 80 CallbackStack::Block::~Block()
30 { 81 {
31 WTF::freePages(m_buffer, m_blockSize * sizeof(Item)); 82 CallbackStackMemoryPool::instance().free(m_buffer);
32 m_buffer = nullptr; 83 m_buffer = nullptr;
33 m_limit = nullptr; 84 m_limit = nullptr;
34 m_current = nullptr; 85 m_current = nullptr;
35 m_next = nullptr; 86 m_next = nullptr;
36 } 87 }
37 88
38 #if ENABLE(ASSERT) 89 #if ENABLE(ASSERT)
39 void CallbackStack::Block::clear() 90 void CallbackStack::Block::clear()
40 { 91 {
41 for (size_t i = 0; i < m_blockSize; i++) 92 for (size_t i = 0; i < CallbackStackMemoryPool::kBlockSize; i++)
42 m_buffer[i] = Item(0, 0); 93 m_buffer[i] = Item(0, 0);
43 } 94 }
44 #endif 95 #endif
45 96
46 void CallbackStack::Block::decommit()
47 {
48 reset();
49 WTF::discardSystemPages(m_buffer, m_blockSize * sizeof(Item));
50 }
51
52 void CallbackStack::Block::reset()
53 {
54 #if ENABLE(ASSERT)
55 clear();
56 #endif
57 m_current = &m_buffer[0];
58 m_next = nullptr;
59 }
60
61 void CallbackStack::Block::invokeEphemeronCallbacks(Visitor* visitor) 97 void CallbackStack::Block::invokeEphemeronCallbacks(Visitor* visitor)
62 { 98 {
63 // This loop can tolerate entries being added by the callbacks after 99 // This loop can tolerate entries being added by the callbacks after
64 // iteration starts. 100 // iteration starts.
65 for (unsigned i = 0; m_buffer + i < m_current; i++) { 101 for (unsigned i = 0; m_buffer + i < m_current; i++) {
66 Item& item = m_buffer[i]; 102 Item& item = m_buffer[i];
67 item.call(visitor); 103 item.call(visitor);
68 } 104 }
69 } 105 }
70 106
71 #if ENABLE(ASSERT) 107 #if ENABLE(ASSERT)
72 bool CallbackStack::Block::hasCallbackForObject(const void* object) 108 bool CallbackStack::Block::hasCallbackForObject(const void* object)
73 { 109 {
74 for (unsigned i = 0; m_buffer + i < m_current; i++) { 110 for (unsigned i = 0; m_buffer + i < m_current; i++) {
75 Item* item = &m_buffer[i]; 111 Item* item = &m_buffer[i];
76 if (item->object() == object) 112 if (item->object() == object)
77 return true; 113 return true;
78 } 114 }
79 return false; 115 return false;
80 } 116 }
81 #endif 117 #endif
82 118
83 CallbackStack::CallbackStack(size_t blockSize) 119 std::unique_ptr<CallbackStack> CallbackStack::create()
84 : m_first(new Block(nullptr, blockSize)) 120 {
85 , m_last(m_first) 121 return wrapUnique(new CallbackStack());
122 }
123
124 CallbackStack::CallbackStack()
125 : m_first(nullptr)
126 , m_last(nullptr)
86 { 127 {
87 } 128 }
88 129
89 CallbackStack::~CallbackStack() 130 CallbackStack::~CallbackStack()
90 { 131 {
91 RELEASE_ASSERT(isEmpty()); 132 CHECK(isEmpty());
92 delete m_first;
93 m_first = nullptr; 133 m_first = nullptr;
94 m_last = nullptr; 134 m_last = nullptr;
95 } 135 }
96 136
97 void CallbackStack::clear() 137 void CallbackStack::commit()
98 { 138 {
139 DCHECK(!m_first);
140 m_first = new Block(m_first);
141 m_last = m_first;
142 }
143
144 void CallbackStack::decommit()
145 {
146 if (!m_first)
147 return;
99 Block* next; 148 Block* next;
100 for (Block* current = m_first->next(); current; current = next) { 149 for (Block* current = m_first->next(); current; current = next) {
101 next = current->next(); 150 next = current->next();
102 delete current; 151 delete current;
103 } 152 }
104 m_first->reset(); 153 delete m_first;
105 m_last = m_first; 154 m_last = m_first = nullptr;
106 }
107
108 void CallbackStack::decommit()
109 {
110 Block* next;
111 for (Block* current = m_first->next(); current; current = next) {
112 next = current->next();
113 delete current;
114 }
115 m_first->decommit();
116 m_last = m_first;
117 } 155 }
118 156
119 bool CallbackStack::isEmpty() const 157 bool CallbackStack::isEmpty() const
120 { 158 {
121 return hasJustOneBlock() && m_first->isEmptyBlock(); 159 return !m_first || (hasJustOneBlock() && m_first->isEmptyBlock());
122 } 160 }
123 161
124 CallbackStack::Item* CallbackStack::allocateEntrySlow() 162 CallbackStack::Item* CallbackStack::allocateEntrySlow()
125 { 163 {
126 ASSERT(!m_first->allocateEntry()); 164 DCHECK(m_first);
127 m_first = new Block(m_first, m_first->blockSize()); 165 DCHECK(!m_first->allocateEntry());
166 m_first = new Block(m_first);
128 return m_first->allocateEntry(); 167 return m_first->allocateEntry();
129 } 168 }
130 169
131 CallbackStack::Item* CallbackStack::popSlow() 170 CallbackStack::Item* CallbackStack::popSlow()
132 { 171 {
133 ASSERT(m_first->isEmptyBlock()); 172 DCHECK(m_first);
173 DCHECK(m_first->isEmptyBlock());
134 174
135 for (;;) { 175 for (;;) {
136 Block* next = m_first->next(); 176 Block* next = m_first->next();
137 if (!next) { 177 if (!next) {
138 #if ENABLE(ASSERT) 178 #if ENABLE(ASSERT)
139 m_first->clear(); 179 m_first->clear();
140 #endif 180 #endif
141 return nullptr; 181 return nullptr;
142 } 182 }
143 delete m_first; 183 delete m_first;
(...skipping 18 matching lines...) Expand all
162 upto = from; 202 upto = from;
163 from = m_first; 203 from = m_first;
164 invokeOldestCallbacks(from, upto, visitor); 204 invokeOldestCallbacks(from, upto, visitor);
165 } 205 }
166 } 206 }
167 207
168 void CallbackStack::invokeOldestCallbacks(Block* from, Block* upto, Visitor* vis itor) 208 void CallbackStack::invokeOldestCallbacks(Block* from, Block* upto, Visitor* vis itor)
169 { 209 {
170 if (from == upto) 210 if (from == upto)
171 return; 211 return;
172 ASSERT(from); 212 DCHECK(from);
173 // Recurse first so we get to the newly added entries last. 213 // Recurse first so we get to the newly added entries last.
174 invokeOldestCallbacks(from->next(), upto, visitor); 214 invokeOldestCallbacks(from->next(), upto, visitor);
175 from->invokeEphemeronCallbacks(visitor); 215 from->invokeEphemeronCallbacks(visitor);
176 } 216 }
177 217
178 bool CallbackStack::hasJustOneBlock() const 218 bool CallbackStack::hasJustOneBlock() const
179 { 219 {
220 DCHECK(m_first);
180 return !m_first->next(); 221 return !m_first->next();
181 } 222 }
182 223
183 #if ENABLE(ASSERT) 224 #if ENABLE(ASSERT)
184 bool CallbackStack::hasCallbackForObject(const void* object) 225 bool CallbackStack::hasCallbackForObject(const void* object)
185 { 226 {
186 for (Block* current = m_first; current; current = current->next()) { 227 for (Block* current = m_first; current; current = current->next()) {
187 if (current->hasCallbackForObject(object)) 228 if (current->hasCallbackForObject(object))
188 return true; 229 return true;
189 } 230 }
190 return false; 231 return false;
191 } 232 }
192 #endif 233 #endif
193 234
194 } // namespace blink 235 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/heap/CallbackStack.h ('k') | third_party/WebKit/Source/platform/heap/Heap.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698