OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. |
3 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 3 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. 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 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 24 matching lines...) Expand all Loading... |
35 #ifdef SHARED_BUFFER_STATS | 35 #ifdef SHARED_BUFFER_STATS |
36 #include "public/platform/Platform.h" | 36 #include "public/platform/Platform.h" |
37 #include "public/platform/WebTaskRunner.h" | 37 #include "public/platform/WebTaskRunner.h" |
38 #include "public/platform/WebTraceLocation.h" | 38 #include "public/platform/WebTraceLocation.h" |
39 #include "wtf/DataLog.h" | 39 #include "wtf/DataLog.h" |
40 #include <set> | 40 #include <set> |
41 #endif | 41 #endif |
42 | 42 |
43 namespace blink { | 43 namespace blink { |
44 | 44 |
45 static inline unsigned segmentIndex(unsigned position) | 45 static inline size_t segmentIndex(size_t position) |
46 { | 46 { |
47 return position / SharedBuffer::kSegmentSize; | 47 return position / SharedBuffer::kSegmentSize; |
48 } | 48 } |
49 | 49 |
50 static inline unsigned offsetInSegment(unsigned position) | 50 static inline size_t offsetInSegment(size_t position) |
51 { | 51 { |
52 return position % SharedBuffer::kSegmentSize; | 52 return position % SharedBuffer::kSegmentSize; |
53 } | 53 } |
54 | 54 |
55 static inline char* allocateSegment() | 55 static inline char* allocateSegment() |
56 { | 56 { |
57 return static_cast<char*>(WTF::Partitions::fastMalloc(SharedBuffer::kSegment
Size, "blink::SharedBuffer")); | 57 return static_cast<char*>(WTF::Partitions::fastMalloc(SharedBuffer::kSegment
Size, "blink::SharedBuffer")); |
58 } | 58 } |
59 | 59 |
60 static inline void freeSegment(char* p) | 60 static inline void freeSegment(char* p) |
(...skipping 17 matching lines...) Expand all Loading... |
78 return buffers; | 78 return buffers; |
79 } | 79 } |
80 | 80 |
81 static bool sizeComparator(SharedBuffer* a, SharedBuffer* b) | 81 static bool sizeComparator(SharedBuffer* a, SharedBuffer* b) |
82 { | 82 { |
83 return a->size() > b->size(); | 83 return a->size() > b->size(); |
84 } | 84 } |
85 | 85 |
86 static CString snippetForBuffer(SharedBuffer* sharedBuffer) | 86 static CString snippetForBuffer(SharedBuffer* sharedBuffer) |
87 { | 87 { |
88 const unsigned kMaxSnippetLength = 64; | 88 const size_t kMaxSnippetLength = 64; |
89 char* snippet = 0; | 89 char* snippet = 0; |
90 unsigned snippetLength = std::min(sharedBuffer->size(), kMaxSnippetLength); | 90 size_t snippetLength = std::min(sharedBuffer->size(), kMaxSnippetLength); |
91 CString result = CString::newUninitialized(snippetLength, snippet); | 91 CString result = CString::newUninitialized(snippetLength, snippet); |
92 | 92 |
93 const char* segment; | 93 const char* segment; |
94 unsigned offset = 0; | 94 size_t offset = 0; |
95 while (unsigned segmentLength = sharedBuffer->getSomeData(segment, offset))
{ | 95 while (size_t segmentLength = sharedBuffer->getSomeDataInternal(segment, off
set)) { |
96 unsigned length = std::min(segmentLength, snippetLength - offset); | 96 size_t length = std::min(segmentLength, snippetLength - offset); |
97 memcpy(snippet + offset, segment, length); | 97 memcpy(snippet + offset, segment, length); |
98 offset += segmentLength; | 98 offset += segmentLength; |
99 if (offset >= snippetLength) | 99 if (offset >= snippetLength) |
100 break; | 100 break; |
101 } | 101 } |
102 | 102 |
103 for (unsigned i = 0; i < snippetLength; ++i) { | 103 for (size_t i = 0; i < snippetLength; ++i) { |
104 if (!isASCIIPrintable(snippet[i])) | 104 if (!isASCIIPrintable(snippet[i])) |
105 snippet[i] = '?'; | 105 snippet[i] = '?'; |
106 } | 106 } |
107 | 107 |
108 return result; | 108 return result; |
109 } | 109 } |
110 | 110 |
111 static void printStats() | 111 static void printStats() |
112 { | 112 { |
113 MutexLocker locker(statsMutex()); | 113 MutexLocker locker(statsMutex()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 : m_size(size) | 152 : m_size(size) |
153 , m_buffer(PurgeableVector::NotPurgeable) | 153 , m_buffer(PurgeableVector::NotPurgeable) |
154 { | 154 { |
155 m_buffer.reserveCapacity(size); | 155 m_buffer.reserveCapacity(size); |
156 m_buffer.grow(size); | 156 m_buffer.grow(size); |
157 #ifdef SHARED_BUFFER_STATS | 157 #ifdef SHARED_BUFFER_STATS |
158 didCreateSharedBuffer(this); | 158 didCreateSharedBuffer(this); |
159 #endif | 159 #endif |
160 } | 160 } |
161 | 161 |
162 SharedBuffer::SharedBuffer(const char* data, int size) | 162 SharedBuffer::SharedBuffer(const char* data, size_t size) |
163 : m_size(0) | 163 : m_size(0) |
164 , m_buffer(PurgeableVector::NotPurgeable) | 164 , m_buffer(PurgeableVector::NotPurgeable) |
165 { | 165 { |
166 // FIXME: Use unsigned consistently, and check for invalid casts when callin
g into SharedBuffer from other code. | 166 appendInternal(data, size); |
167 if (size < 0) | |
168 CRASH(); | |
169 | |
170 append(data, size); | |
171 | 167 |
172 #ifdef SHARED_BUFFER_STATS | 168 #ifdef SHARED_BUFFER_STATS |
173 didCreateSharedBuffer(this); | 169 didCreateSharedBuffer(this); |
174 #endif | 170 #endif |
175 } | 171 } |
176 | 172 |
177 SharedBuffer::SharedBuffer(const char* data, unsigned size, PurgeableVector::Pur
geableOption purgeable) | 173 SharedBuffer::SharedBuffer(const char* data, size_t size, PurgeableVector::Purge
ableOption purgeable) |
178 : m_size(0) | 174 : m_size(0) |
179 , m_buffer(purgeable) | 175 , m_buffer(purgeable) |
180 { | 176 { |
181 append(data, size); | 177 appendInternal(data, size); |
182 | 178 |
183 #ifdef SHARED_BUFFER_STATS | 179 #ifdef SHARED_BUFFER_STATS |
184 didCreateSharedBuffer(this); | 180 didCreateSharedBuffer(this); |
185 #endif | 181 #endif |
186 } | 182 } |
187 | 183 |
188 SharedBuffer::SharedBuffer(const unsigned char* data, int size) | 184 SharedBuffer::SharedBuffer(const unsigned char* data, size_t size) |
189 : m_size(0) | 185 : m_size(0) |
190 , m_buffer(PurgeableVector::NotPurgeable) | 186 , m_buffer(PurgeableVector::NotPurgeable) |
191 { | 187 { |
192 // FIXME: Use unsigned consistently, and check for invalid casts when callin
g into SharedBuffer from other code. | 188 appendInternal(reinterpret_cast<const char*>(data), size); |
193 if (size < 0) | |
194 CRASH(); | |
195 | |
196 append(reinterpret_cast<const char*>(data), size); | |
197 | 189 |
198 #ifdef SHARED_BUFFER_STATS | 190 #ifdef SHARED_BUFFER_STATS |
199 didCreateSharedBuffer(this); | 191 didCreateSharedBuffer(this); |
200 #endif | 192 #endif |
201 } | 193 } |
202 | 194 |
203 SharedBuffer::~SharedBuffer() | 195 SharedBuffer::~SharedBuffer() |
204 { | 196 { |
205 clear(); | 197 clear(); |
206 | 198 |
207 #ifdef SHARED_BUFFER_STATS | 199 #ifdef SHARED_BUFFER_STATS |
208 willDestroySharedBuffer(this); | 200 willDestroySharedBuffer(this); |
209 #endif | 201 #endif |
210 } | 202 } |
211 | 203 |
212 PassRefPtr<SharedBuffer> SharedBuffer::adoptVector(Vector<char>& vector) | 204 PassRefPtr<SharedBuffer> SharedBuffer::adoptVector(Vector<char>& vector) |
213 { | 205 { |
214 RefPtr<SharedBuffer> buffer = create(); | 206 RefPtr<SharedBuffer> buffer = create(); |
215 buffer->m_buffer.adopt(vector); | 207 buffer->m_buffer.adopt(vector); |
216 buffer->m_size = buffer->m_buffer.size(); | 208 buffer->m_size = buffer->m_buffer.size(); |
217 return buffer.release(); | 209 return buffer.release(); |
218 } | 210 } |
219 | 211 |
220 unsigned SharedBuffer::size() const | 212 size_t SharedBuffer::size() const |
221 { | 213 { |
222 return m_size; | 214 return m_size; |
223 } | 215 } |
224 | 216 |
225 const char* SharedBuffer::data() const | 217 const char* SharedBuffer::data() const |
226 { | 218 { |
227 mergeSegmentsIntoBuffer(); | 219 mergeSegmentsIntoBuffer(); |
228 return m_buffer.data(); | 220 return m_buffer.data(); |
229 } | 221 } |
230 | 222 |
231 void SharedBuffer::append(PassRefPtr<SharedBuffer> data) | 223 void SharedBuffer::append(PassRefPtr<SharedBuffer> data) |
232 { | 224 { |
233 const char* segment; | 225 const char* segment; |
234 size_t position = 0; | 226 size_t position = 0; |
235 while (size_t length = data->getSomeData(segment, position)) { | 227 while (size_t length = data->getSomeDataInternal(segment, position)) { |
236 append(segment, length); | 228 append(segment, length); |
237 position += length; | 229 position += length; |
238 } | 230 } |
239 } | 231 } |
240 | 232 |
241 void SharedBuffer::append(const char* data, unsigned length) | 233 void SharedBuffer::appendInternal(const char* data, size_t length) |
242 { | 234 { |
243 ASSERT(isLocked()); | 235 ASSERT(isLocked()); |
244 if (!length) | 236 if (!length) |
245 return; | 237 return; |
246 | 238 |
247 ASSERT(m_size >= m_buffer.size()); | 239 ASSERT(m_size >= m_buffer.size()); |
248 unsigned positionInSegment = offsetInSegment(m_size - m_buffer.size()); | 240 size_t positionInSegment = offsetInSegment(m_size - m_buffer.size()); |
249 m_size += length; | 241 m_size += length; |
250 | 242 |
251 if (m_size <= kSegmentSize) { | 243 if (m_size <= kSegmentSize) { |
252 // No need to use segments for small resource data. | 244 // No need to use segments for small resource data. |
253 m_buffer.append(data, length); | 245 m_buffer.append(data, length); |
254 return; | 246 return; |
255 } | 247 } |
256 | 248 |
257 char* segment; | 249 char* segment; |
258 if (!positionInSegment) { | 250 if (!positionInSegment) { |
259 segment = allocateSegment(); | 251 segment = allocateSegment(); |
260 m_segments.append(segment); | 252 m_segments.append(segment); |
261 } else | 253 } else |
262 segment = m_segments.last() + positionInSegment; | 254 segment = m_segments.last() + positionInSegment; |
263 | 255 |
264 unsigned segmentFreeSpace = kSegmentSize - positionInSegment; | 256 size_t segmentFreeSpace = kSegmentSize - positionInSegment; |
265 unsigned bytesToCopy = std::min(length, segmentFreeSpace); | 257 size_t bytesToCopy = std::min(length, segmentFreeSpace); |
266 | 258 |
267 for (;;) { | 259 for (;;) { |
268 memcpy(segment, data, bytesToCopy); | 260 memcpy(segment, data, bytesToCopy); |
269 if (static_cast<unsigned>(length) == bytesToCopy) | 261 if (length == bytesToCopy) |
270 break; | 262 break; |
271 | 263 |
272 length -= bytesToCopy; | 264 length -= bytesToCopy; |
273 data += bytesToCopy; | 265 data += bytesToCopy; |
274 segment = allocateSegment(); | 266 segment = allocateSegment(); |
275 m_segments.append(segment); | 267 m_segments.append(segment); |
276 bytesToCopy = std::min(length, static_cast<unsigned>(kSegmentSize)); | 268 bytesToCopy = std::min(length, static_cast<size_t>(kSegmentSize)); |
277 } | 269 } |
278 } | 270 } |
279 | 271 |
280 void SharedBuffer::append(const Vector<char>& data) | 272 void SharedBuffer::append(const Vector<char>& data) |
281 { | 273 { |
282 append(data.data(), data.size()); | 274 append(data.data(), data.size()); |
283 } | 275 } |
284 | 276 |
285 void SharedBuffer::clear() | 277 void SharedBuffer::clear() |
286 { | 278 { |
287 for (unsigned i = 0; i < m_segments.size(); ++i) | 279 for (size_t i = 0; i < m_segments.size(); ++i) |
288 freeSegment(m_segments[i]); | 280 freeSegment(m_segments[i]); |
289 | 281 |
290 m_segments.clear(); | 282 m_segments.clear(); |
291 m_size = 0; | 283 m_size = 0; |
292 m_buffer.clear(); | 284 m_buffer.clear(); |
293 } | 285 } |
294 | 286 |
295 PassRefPtr<SharedBuffer> SharedBuffer::copy() const | 287 PassRefPtr<SharedBuffer> SharedBuffer::copy() const |
296 { | 288 { |
297 RefPtr<SharedBuffer> clone(adoptRef(new SharedBuffer)); | 289 RefPtr<SharedBuffer> clone(adoptRef(new SharedBuffer)); |
298 clone->m_size = m_size; | 290 clone->m_size = m_size; |
299 clone->m_buffer.reserveCapacity(m_size); | 291 clone->m_buffer.reserveCapacity(m_size); |
300 clone->m_buffer.append(m_buffer.data(), m_buffer.size()); | 292 clone->m_buffer.append(m_buffer.data(), m_buffer.size()); |
301 if (!m_segments.isEmpty()) { | 293 if (!m_segments.isEmpty()) { |
302 const char* segment = 0; | 294 const char* segment = 0; |
303 unsigned position = m_buffer.size(); | 295 size_t position = m_buffer.size(); |
304 while (unsigned segmentSize = getSomeData(segment, position)) { | 296 while (size_t segmentSize = getSomeDataInternal(segment, position)) { |
305 clone->m_buffer.append(segment, segmentSize); | 297 clone->m_buffer.append(segment, segmentSize); |
306 position += segmentSize; | 298 position += segmentSize; |
307 } | 299 } |
308 ASSERT(position == clone->size()); | 300 ASSERT(position == clone->size()); |
309 } | 301 } |
310 return clone.release(); | 302 return clone.release(); |
311 } | 303 } |
312 | 304 |
313 void SharedBuffer::mergeSegmentsIntoBuffer() const | 305 void SharedBuffer::mergeSegmentsIntoBuffer() const |
314 { | 306 { |
315 unsigned bufferSize = m_buffer.size(); | 307 size_t bufferSize = m_buffer.size(); |
316 if (m_size > bufferSize) { | 308 if (m_size > bufferSize) { |
317 unsigned bytesLeft = m_size - bufferSize; | 309 size_t bytesLeft = m_size - bufferSize; |
318 for (unsigned i = 0; i < m_segments.size(); ++i) { | 310 for (size_t i = 0; i < m_segments.size(); ++i) { |
319 unsigned bytesToCopy = std::min(bytesLeft, static_cast<unsigned>(kSe
gmentSize)); | 311 size_t bytesToCopy = std::min(bytesLeft, static_cast<size_t>(kSegmen
tSize)); |
320 m_buffer.append(m_segments[i], bytesToCopy); | 312 m_buffer.append(m_segments[i], bytesToCopy); |
321 bytesLeft -= bytesToCopy; | 313 bytesLeft -= bytesToCopy; |
322 freeSegment(m_segments[i]); | 314 freeSegment(m_segments[i]); |
323 } | 315 } |
324 m_segments.clear(); | 316 m_segments.clear(); |
325 } | 317 } |
326 } | 318 } |
327 | 319 |
328 unsigned SharedBuffer::getSomeData(const char*& someData, unsigned position) con
st | 320 size_t SharedBuffer::getSomeDataInternal(const char*& someData, size_t position)
const |
329 { | 321 { |
330 ASSERT(isLocked()); | 322 ASSERT(isLocked()); |
331 unsigned totalSize = size(); | 323 size_t totalSize = size(); |
332 if (position >= totalSize) { | 324 if (position >= totalSize) { |
333 someData = 0; | 325 someData = 0; |
334 return 0; | 326 return 0; |
335 } | 327 } |
336 | 328 |
337 ASSERT_WITH_SECURITY_IMPLICATION(position < m_size); | 329 ASSERT_WITH_SECURITY_IMPLICATION(position < m_size); |
338 unsigned consecutiveSize = m_buffer.size(); | 330 size_t consecutiveSize = m_buffer.size(); |
339 if (position < consecutiveSize) { | 331 if (position < consecutiveSize) { |
340 someData = m_buffer.data() + position; | 332 someData = m_buffer.data() + position; |
341 return consecutiveSize - position; | 333 return consecutiveSize - position; |
342 } | 334 } |
343 | 335 |
344 position -= consecutiveSize; | 336 position -= consecutiveSize; |
345 unsigned segments = m_segments.size(); | 337 size_t segments = m_segments.size(); |
346 unsigned maxSegmentedSize = segments * kSegmentSize; | 338 size_t maxSegmentedSize = segments * kSegmentSize; |
347 unsigned segment = segmentIndex(position); | 339 size_t segment = segmentIndex(position); |
348 if (segment < segments) { | 340 if (segment < segments) { |
349 unsigned bytesLeft = totalSize - consecutiveSize; | 341 size_t bytesLeft = totalSize - consecutiveSize; |
350 unsigned segmentedSize = std::min(maxSegmentedSize, bytesLeft); | 342 size_t segmentedSize = std::min(maxSegmentedSize, bytesLeft); |
351 | 343 |
352 unsigned positionInSegment = offsetInSegment(position); | 344 size_t positionInSegment = offsetInSegment(position); |
353 someData = m_segments[segment] + positionInSegment; | 345 someData = m_segments[segment] + positionInSegment; |
354 return segment == segments - 1 ? segmentedSize - position : kSegmentSize
- positionInSegment; | 346 return segment == segments - 1 ? segmentedSize - position : kSegmentSize
- positionInSegment; |
355 } | 347 } |
356 ASSERT_NOT_REACHED(); | 348 ASSERT_NOT_REACHED(); |
357 return 0; | 349 return 0; |
358 } | 350 } |
359 | 351 |
360 bool SharedBuffer::getAsBytes(void* dest, unsigned byteLength) const | 352 bool SharedBuffer::getAsBytesInternal(void* dest, size_t byteLength) const |
361 { | 353 { |
362 if (!dest || byteLength != size()) | 354 if (!dest || byteLength != size()) |
363 return false; | 355 return false; |
364 | 356 |
365 const char* segment = 0; | 357 const char* segment = 0; |
366 unsigned position = 0; | 358 size_t position = 0; |
367 while (unsigned segmentSize = getSomeData(segment, position)) { | 359 while (size_t segmentSize = getSomeDataInternal(segment, position)) { |
368 memcpy(static_cast<char*>(dest) + position, segment, segmentSize); | 360 memcpy(static_cast<char*>(dest) + position, segment, segmentSize); |
369 position += segmentSize; | 361 position += segmentSize; |
370 } | 362 } |
371 | 363 |
372 if (position != byteLength) { | 364 if (position != byteLength) { |
373 ASSERT_NOT_REACHED(); | 365 ASSERT_NOT_REACHED(); |
374 // Don't return the incomplete data. | 366 // Don't return the incomplete data. |
375 return false; | 367 return false; |
376 } | 368 } |
377 | 369 |
378 return true; | 370 return true; |
379 } | 371 } |
380 | 372 |
381 PassRefPtr<SkData> SharedBuffer::getAsSkData() const | 373 PassRefPtr<SkData> SharedBuffer::getAsSkData() const |
382 { | 374 { |
383 unsigned bufferLength = size(); | 375 size_t bufferLength = size(); |
384 SkData* data = SkData::NewUninitialized(bufferLength); | 376 SkData* data = SkData::NewUninitialized(bufferLength); |
385 char* buffer = static_cast<char*>(data->writable_data()); | 377 char* buffer = static_cast<char*>(data->writable_data()); |
386 const char* segment = 0; | 378 const char* segment = 0; |
387 unsigned position = 0; | 379 size_t position = 0; |
388 while (unsigned segmentSize = getSomeData(segment, position)) { | 380 while (size_t segmentSize = getSomeDataInternal(segment, position)) { |
389 memcpy(buffer + position, segment, segmentSize); | 381 memcpy(buffer + position, segment, segmentSize); |
390 position += segmentSize; | 382 position += segmentSize; |
391 } | 383 } |
392 | 384 |
393 if (position != bufferLength) { | 385 if (position != bufferLength) { |
394 ASSERT_NOT_REACHED(); | 386 ASSERT_NOT_REACHED(); |
395 // Don't return the incomplete SkData. | 387 // Don't return the incomplete SkData. |
396 return nullptr; | 388 return nullptr; |
397 } | 389 } |
398 return adoptRef(data); | 390 return adoptRef(data); |
(...skipping 23 matching lines...) Expand all Loading... |
422 // If there is data in the segments, then it should have been allocated | 414 // If there is data in the segments, then it should have been allocated |
423 // using fastMalloc. | 415 // using fastMalloc. |
424 const String dataDumpName = dumpPrefix + "/segments"; | 416 const String dataDumpName = dumpPrefix + "/segments"; |
425 auto dump = memoryDump->createMemoryAllocatorDump(dataDumpName); | 417 auto dump = memoryDump->createMemoryAllocatorDump(dataDumpName); |
426 dump->addScalar("size", "bytes", m_size); | 418 dump->addScalar("size", "bytes", m_size); |
427 memoryDump->addSuballocation(dump->guid(), String(WTF::Partitions::kAllo
catedObjectPoolName)); | 419 memoryDump->addSuballocation(dump->guid(), String(WTF::Partitions::kAllo
catedObjectPoolName)); |
428 } | 420 } |
429 } | 421 } |
430 | 422 |
431 } // namespace blink | 423 } // namespace blink |
OLD | NEW |