OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2014 Google Inc. All rights reserved. | 2 * Copyright (C) 2014 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 | 43 |
44 // DiscardableMemory allocations are expensive and page-grained. We only use | 44 // DiscardableMemory allocations are expensive and page-grained. We only use |
45 // them when there's a reasonable amount of memory to be saved by the OS | 45 // them when there's a reasonable amount of memory to be saved by the OS |
46 // discarding the memory. | 46 // discarding the memory. |
47 static const size_t minimumDiscardableAllocationSize = 4 * 4096; | 47 static const size_t minimumDiscardableAllocationSize = 4 * 4096; |
48 | 48 |
49 PurgeableVector::PurgeableVector(PurgeableOption purgeable) | 49 PurgeableVector::PurgeableVector(PurgeableOption purgeable) |
50 : m_discardableCapacity(0) | 50 : m_discardableCapacity(0) |
51 , m_discardableSize(0) | 51 , m_discardableSize(0) |
52 , m_isPurgeable(purgeable == Purgeable) | 52 , m_isPurgeable(purgeable == Purgeable) |
53 , m_locksCount(1) // The buffer is locked at creation. | |
54 { | 53 { |
55 } | 54 } |
56 | 55 |
57 PurgeableVector::~PurgeableVector() | 56 PurgeableVector::~PurgeableVector() |
58 { | 57 { |
59 } | 58 } |
60 | 59 |
61 void PurgeableVector::reserveCapacity(size_t capacity) | 60 void PurgeableVector::reserveCapacity(size_t capacity) |
62 { | 61 { |
63 ASSERT(isLocked()); | |
64 | |
65 if (m_isPurgeable) { | 62 if (m_isPurgeable) { |
66 if (reservePurgeableCapacity(capacity, UseExactCapacity)) | 63 if (reservePurgeableCapacity(capacity, UseExactCapacity)) |
67 return; | 64 return; |
68 // Fallback to non-purgeable buffer allocation in case discardable memor
y allocation failed. | 65 // Fallback to non-purgeable buffer allocation in case discardable memor
y allocation failed. |
69 } | 66 } |
70 | 67 |
71 if (!m_vector.capacity()) { | 68 if (!m_vector.capacity()) { |
72 // Using reserveInitialCapacity() on the underlying vector ensures that
the vector uses the | 69 // Using reserveInitialCapacity() on the underlying vector ensures that
the vector uses the |
73 // exact specified capacity to avoid consuming too much memory for small
resources. | 70 // exact specified capacity to avoid consuming too much memory for small
resources. |
74 m_vector.reserveInitialCapacity(capacity); | 71 m_vector.reserveInitialCapacity(capacity); |
(...skipping 28 matching lines...) Expand all Loading... |
103 | 100 |
104 void PurgeableVector::clearDiscardable() | 101 void PurgeableVector::clearDiscardable() |
105 { | 102 { |
106 m_discardable = nullptr; | 103 m_discardable = nullptr; |
107 m_discardableCapacity = 0; | 104 m_discardableCapacity = 0; |
108 m_discardableSize = 0; | 105 m_discardableSize = 0; |
109 } | 106 } |
110 | 107 |
111 void PurgeableVector::append(const char* data, size_t length) | 108 void PurgeableVector::append(const char* data, size_t length) |
112 { | 109 { |
113 ASSERT(isLocked()); | |
114 | |
115 if (!m_isPurgeable) { | 110 if (!m_isPurgeable) { |
116 m_vector.append(data, length); | 111 m_vector.append(data, length); |
117 return; | 112 return; |
118 } | 113 } |
119 | 114 |
120 const size_t currentSize = m_discardable ? m_discardableSize : m_vector.size
(); | 115 const size_t currentSize = m_discardable ? m_discardableSize : m_vector.size
(); |
121 const size_t newBufferSize = currentSize + length; | 116 const size_t newBufferSize = currentSize + length; |
122 | 117 |
123 if (!reservePurgeableCapacity(newBufferSize, UseExponentialGrowth)) { | 118 if (!reservePurgeableCapacity(newBufferSize, UseExponentialGrowth)) { |
124 moveDataFromDiscardableToVector(); | 119 moveDataFromDiscardableToVector(); |
(...skipping 22 matching lines...) Expand all Loading... |
147 } | 142 } |
148 | 143 |
149 void PurgeableVector::clear() | 144 void PurgeableVector::clear() |
150 { | 145 { |
151 clearDiscardable(); | 146 clearDiscardable(); |
152 m_vector.clear(); | 147 m_vector.clear(); |
153 } | 148 } |
154 | 149 |
155 char* PurgeableVector::data() | 150 char* PurgeableVector::data() |
156 { | 151 { |
157 ASSERT(isLocked()); | |
158 return m_discardable ? static_cast<char*>(m_discardable->data()) : m_vector.
data(); | 152 return m_discardable ? static_cast<char*>(m_discardable->data()) : m_vector.
data(); |
159 } | 153 } |
160 | 154 |
161 size_t PurgeableVector::size() const | 155 size_t PurgeableVector::size() const |
162 { | 156 { |
163 return m_discardable ? m_discardableSize : m_vector.size(); | 157 return m_discardable ? m_discardableSize : m_vector.size(); |
164 } | 158 } |
165 | 159 |
166 void PurgeableVector::adopt(Vector<char>& other) | 160 void PurgeableVector::adopt(Vector<char>& other) |
167 { | 161 { |
168 if (size() > 0) | 162 if (size() > 0) |
169 clear(); | 163 clear(); |
170 | 164 |
171 if (!m_isPurgeable) { | 165 if (!m_isPurgeable) { |
172 m_vector.swap(other); | 166 m_vector.swap(other); |
173 return; | 167 return; |
174 } | 168 } |
175 | 169 |
176 if (other.isEmpty()) | 170 if (other.isEmpty()) |
177 return; | 171 return; |
178 | 172 |
179 append(other.data(), other.size()); | 173 append(other.data(), other.size()); |
180 other.clear(); | 174 other.clear(); |
181 } | 175 } |
182 | 176 |
183 bool PurgeableVector::lock() | |
184 { | |
185 ++m_locksCount; | |
186 if (m_locksCount > 1) | |
187 return true; | |
188 | |
189 ASSERT(m_locksCount == 1); | |
190 if (!m_discardable) | |
191 return true; | |
192 | |
193 return m_discardable->Lock(); | |
194 } | |
195 | |
196 void PurgeableVector::unlock() | |
197 { | |
198 ASSERT(isLocked()); | |
199 --m_locksCount; | |
200 if (m_locksCount > 0) | |
201 return; | |
202 | |
203 if (!m_vector.isEmpty()) { | |
204 ASSERT(!m_discardable); | |
205 m_isPurgeable = true; | |
206 if (!reservePurgeableCapacity(m_vector.size(), UseExactCapacity)) | |
207 return; | |
208 } | |
209 | |
210 if (m_discardable) | |
211 m_discardable->Unlock(); | |
212 } | |
213 | |
214 bool PurgeableVector::isLocked() const | |
215 { | |
216 ASSERT(m_locksCount >= 0); | |
217 return m_locksCount > 0; | |
218 } | |
219 | |
220 bool PurgeableVector::reservePurgeableCapacity(size_t capacity, PurgeableAllocat
ionStrategy allocationStrategy) | 177 bool PurgeableVector::reservePurgeableCapacity(size_t capacity, PurgeableAllocat
ionStrategy allocationStrategy) |
221 { | 178 { |
222 ASSERT(m_isPurgeable); | 179 ASSERT(m_isPurgeable); |
223 | 180 |
224 if (m_discardable && m_discardableCapacity >= capacity) { | 181 if (m_discardable && m_discardableCapacity >= capacity) { |
225 ASSERT(!m_vector.capacity()); | 182 ASSERT(!m_vector.capacity()); |
226 return true; | 183 return true; |
227 } | 184 } |
228 | 185 |
229 if (capacity < minimumDiscardableAllocationSize) | 186 if (capacity < minimumDiscardableAllocationSize) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 // fragmentation. | 220 // fragmentation. |
264 // Since the page size is only used below to minimize fragmentation it's sti
ll safe to use it | 221 // Since the page size is only used below to minimize fragmentation it's sti
ll safe to use it |
265 // even if it gets out of sync (e.g. due to the use of huge pages). | 222 // even if it gets out of sync (e.g. due to the use of huge pages). |
266 const size_t kPageSize = 4096; | 223 const size_t kPageSize = 4096; |
267 newCapacity = (newCapacity + kPageSize - 1) & ~(kPageSize - 1); | 224 newCapacity = (newCapacity + kPageSize - 1) & ~(kPageSize - 1); |
268 | 225 |
269 return std::max(capacity, newCapacity); // Overflow check. | 226 return std::max(capacity, newCapacity); // Overflow check. |
270 } | 227 } |
271 | 228 |
272 } // namespace blink | 229 } // namespace blink |
OLD | NEW |