| 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 |