OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
304 T* buffer() { return m_buffer; } | 304 T* buffer() { return m_buffer; } |
305 const T* buffer() const { return m_buffer; } | 305 const T* buffer() const { return m_buffer; } |
306 size_t capacity() const { return m_capacity; } | 306 size_t capacity() const { return m_capacity; } |
307 | 307 |
308 void clearUnusedSlots(T* from, T* to) | 308 void clearUnusedSlots(T* from, T* to) |
309 { | 309 { |
310 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTrai ts<T>::needsDestruction || ShouldBeTraced<VectorTraits<T> >::value), T>::clear(f rom, to); | 310 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTrai ts<T>::needsDestruction || ShouldBeTraced<VectorTraits<T> >::value), T>::clear(f rom, to); |
311 } | 311 } |
312 | 312 |
313 protected: | 313 protected: |
314 static const size_t sizeFieldSize = sizeof(unsigned) * 2 > sizeof(double ) ? sizeof(unsigned) * 2 : sizeof(double); | |
Mikhail
2014/07/23 10:02:47
I do not see 'sizeFieldSize' being used anywhere,
| |
315 | |
314 VectorBufferBase() | 316 VectorBufferBase() |
315 : m_buffer(0) | 317 : m_buffer(0) |
316 , m_capacity(0) | 318 , m_capacity(0) |
317 { | 319 { |
318 } | 320 } |
319 | 321 |
320 VectorBufferBase(T* buffer, size_t capacity) | 322 VectorBufferBase(T* buffer, size_t capacity) |
321 : m_buffer(buffer) | 323 : m_buffer(buffer) |
322 , m_capacity(capacity) | 324 , m_capacity(capacity) |
323 { | 325 { |
324 } | 326 } |
325 | 327 |
328 // Ends are exclusive and if they point at the same element as their | |
329 // start then the range is empty. The end can point one above the last | |
330 // element in the capacity (this only happens for Vector, not for | |
331 // Deque). | |
332 struct Range { | |
Mikhail
2014/07/23 10:02:47
Would be nice to see also the comment how these ra
| |
333 Range(unsigned s = 0, unsigned e = 0) | |
Mikhail
2014/07/23 10:02:47
better 'start' and 'end'
| |
334 : start(s) | |
335 , end(e) | |
336 { | |
337 } | |
338 | |
339 bool IsEmpty() { return start == end; } | |
Mikhail
2014/07/23 10:02:47
nit: const method
| |
340 | |
341 unsigned start; | |
342 unsigned end; | |
343 }; | |
344 | |
345 // Takes a range, which may wrap around at capacity and | |
346 // decomposes it into 0, 1, or 2 ranges, returning a pointer to the | |
347 // last element. | |
348 Range* findRanges(Range* buffer, const Range in, unsigned capacity) | |
Mikhail
2014/07/23 10:02:47
const Range& in
Mikhail
2014/07/23 10:02:47
this function does not use any of class members, s
| |
349 { | |
350 if (in.end > in.start) { | |
351 *buffer++ = in; | |
352 } else if (in.end < in.start) { | |
353 if (in.end) | |
354 *buffer++ = Range(0, in.end); | |
355 ASSERT(in.start != capacity); | |
356 *buffer++ = Range(in.start, capacity); | |
357 } | |
358 return buffer - 1; | |
359 } | |
360 | |
326 T* m_buffer; | 361 T* m_buffer; |
327 unsigned m_capacity; | 362 unsigned m_capacity; |
328 unsigned m_size; | |
329 }; | 363 }; |
330 | 364 |
331 template<typename T, size_t inlineCapacity, typename Allocator = DefaultAllo cator> | 365 template<typename T, size_t inlineCapacity, typename Allocator = DefaultAllo cator> |
332 class VectorBuffer; | 366 class VectorBuffer; |
333 | 367 |
334 template<typename T, typename Allocator> | 368 template<typename T, typename Allocator> |
335 class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, Allocato r> { | 369 class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, Allocato r> { |
336 private: | 370 private: |
337 typedef VectorBufferBase<T, Allocator> Base; | 371 typedef VectorBufferBase<T, Allocator> Base; |
372 | |
373 protected: | |
374 typedef typename Base::Range Range; | |
375 | |
338 public: | 376 public: |
339 VectorBuffer() | 377 VectorBuffer() |
340 { | 378 { |
341 } | 379 } |
342 | 380 |
343 VectorBuffer(size_t capacity) | 381 VectorBuffer(size_t capacity) |
344 { | 382 { |
345 // Calling malloc(0) might take a lock and may actually do an | 383 // Calling malloc(0) might take a lock and may actually do an |
346 // allocation on some systems. | 384 // allocation on some systems. |
347 if (capacity) | 385 if (capacity) |
(...skipping 10 matching lines...) Expand all Loading... | |
358 { | 396 { |
359 Allocator::backingFree(bufferToDeallocate); | 397 Allocator::backingFree(bufferToDeallocate); |
360 } | 398 } |
361 | 399 |
362 void resetBufferPointer() | 400 void resetBufferPointer() |
363 { | 401 { |
364 m_buffer = 0; | 402 m_buffer = 0; |
365 m_capacity = 0; | 403 m_capacity = 0; |
366 } | 404 } |
367 | 405 |
368 void swapVectorBuffer(VectorBuffer<T, 0, Allocator>& other) | 406 void swapVectorBuffer(VectorBuffer<T, 0, Allocator>& other, Range, Range ) |
369 { | 407 { |
370 std::swap(m_buffer, other.m_buffer); | 408 std::swap(m_buffer, other.m_buffer); |
371 std::swap(m_capacity, other.m_capacity); | 409 std::swap(m_capacity, other.m_capacity); |
372 } | 410 } |
373 | 411 |
374 using Base::allocateBuffer; | 412 using Base::allocateBuffer; |
375 using Base::allocationSize; | 413 using Base::allocationSize; |
376 | 414 |
377 using Base::buffer; | 415 using Base::buffer; |
378 using Base::capacity; | 416 using Base::capacity; |
417 using Base::findRanges; | |
379 | 418 |
380 using Base::clearUnusedSlots; | 419 using Base::clearUnusedSlots; |
381 | 420 |
382 bool hasOutOfLineBuffer() const | 421 bool hasOutOfLineBuffer() const |
383 { | 422 { |
384 // When inlineCapacity is 0 we have an out of line buffer if we have a buffer. | 423 // When inlineCapacity is 0 we have an out of line buffer if we have a buffer. |
385 return buffer(); | 424 return buffer(); |
386 } | 425 } |
387 | 426 |
388 protected: | |
389 using Base::m_size; | |
390 | |
391 private: | 427 private: |
392 using Base::m_buffer; | 428 using Base::m_buffer; |
393 using Base::m_capacity; | 429 using Base::m_capacity; |
394 }; | 430 }; |
395 | 431 |
396 template<typename T, size_t inlineCapacity, typename Allocator> | 432 template<typename T, size_t inlineCapacity, typename Allocator> |
397 class VectorBuffer : protected VectorBufferBase<T, Allocator> { | 433 class VectorBuffer : protected VectorBufferBase<T, Allocator> { |
398 WTF_MAKE_NONCOPYABLE(VectorBuffer); | 434 WTF_MAKE_NONCOPYABLE(VectorBuffer); |
399 private: | 435 private: |
400 typedef VectorBufferBase<T, Allocator> Base; | 436 typedef VectorBufferBase<T, Allocator> Base; |
437 | |
438 protected: | |
439 typedef typename Base::Range Range; | |
440 | |
401 public: | 441 public: |
402 VectorBuffer() | 442 VectorBuffer() |
403 : Base(inlineBuffer(), inlineCapacity) | 443 : Base(inlineBuffer(), inlineCapacity) |
404 { | 444 { |
405 } | 445 } |
406 | 446 |
407 VectorBuffer(size_t capacity) | 447 VectorBuffer(size_t capacity) |
408 : Base(inlineBuffer(), inlineCapacity) | 448 : Base(inlineBuffer(), inlineCapacity) |
409 { | 449 { |
410 if (capacity > inlineCapacity) | 450 if (capacity > inlineCapacity) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
443 resetBufferPointer(); | 483 resetBufferPointer(); |
444 } | 484 } |
445 | 485 |
446 size_t allocationSize(size_t capacity) const | 486 size_t allocationSize(size_t capacity) const |
447 { | 487 { |
448 if (capacity <= inlineCapacity) | 488 if (capacity <= inlineCapacity) |
449 return m_inlineBufferSize; | 489 return m_inlineBufferSize; |
450 return Base::allocationSize(capacity); | 490 return Base::allocationSize(capacity); |
451 } | 491 } |
452 | 492 |
453 void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other) | 493 // Swap two vector buffers, both of which have the same non-zero inline |
494 // capacity. After calling this, any entries in the inline buffer of one | |
495 // vector buffer will have been moved to the other inline buffer, and th e | |
496 // m_buffer pointer of each vector buffer will point to the data that th e | |
497 // m_buffer pointer of the other vector buffer was previously pointing a t. | |
498 | |
499 // If the inline capacity is insufficient, then one or both | |
500 // may be using an out-of-line buffer, in which case the inline | |
501 // capacity is unused. Out-of-line buffers can be swapped just by | |
502 // redirecting a buffer pointer, but inline buffers must be swapped | |
503 // using move and swap operations on ranges of elements. | |
504 | |
505 // The ranges | |
Mads Ager (chromium)
2014/08/04 10:17:12
Rewrap the lines.
| |
506 // can be from deques, in which case start may be larger than end, and | |
507 // the range wraps around at the capacity, effectively forming two | |
508 // ranges, one at either end of the inline buffer. The ranges can | |
509 // overlap in many ways and may not have the same size, but the inline | |
510 // capacity is always the same size. | |
Mads Ager (chromium)
2014/08/04 10:17:12
same size -> same
| |
511 void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other, Range thisRange, Range otherRange) | |
454 { | 512 { |
455 typedef VectorTypeOperations<T> TypeOperations; | 513 typedef VectorTypeOperations<T> TypeOperations; |
456 | 514 |
457 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuff er()) { | 515 std::swap(m_capacity, other.m_capacity); |
458 ASSERT(m_capacity == other.m_capacity); | 516 |
459 if (m_size > other.m_size) { | 517 Range thisRanges[2]; |
460 TypeOperations::swap(inlineBuffer(), inlineBuffer() + other. m_size, other.inlineBuffer()); | 518 Range otherRanges[2]; |
461 TypeOperations::move(inlineBuffer() + other.m_size, inlineBu ffer() + m_size, other.inlineBuffer() + other.m_size); | 519 // These point at the last of the 0, 1 or 2 ranges. We |
520 // initialize them to indicate no ranges. | |
521 Range* thisRangePtr = thisRanges - 1; | |
522 Range* otherRangePtr = otherRanges - 1; | |
523 | |
524 T* inlBuf = inlineBuffer(); | |
525 T* otherInlBuf = other.inlineBuffer(); | |
526 | |
527 // Find the 0-2 ranges that need to be moved to this vector buffer's inline buffer. | |
528 if (other.buffer() == otherInlBuf) | |
529 otherRangePtr = findRanges(otherRanges, otherRange, inlineCapaci ty); | |
530 | |
531 if (buffer() == inlBuf) { | |
532 // Find the 0-2 ranges that need to be moved to the other vector buffer's inline buffer. | |
533 thisRangePtr = findRanges(thisRanges, thisRange, inlineCapacity) ; | |
534 if (other.buffer() != otherInlBuf) { | |
535 m_buffer = other.m_buffer; | |
536 other.m_buffer = otherInlBuf; | |
537 } | |
538 } else { | |
539 if (other.buffer() == otherInlBuf) { | |
540 other.m_buffer = m_buffer; | |
541 m_buffer = inlBuf; | |
462 } else { | 542 } else { |
463 TypeOperations::swap(inlineBuffer(), inlineBuffer() + m_size , other.inlineBuffer()); | 543 std::swap(m_buffer, other.m_buffer); |
464 TypeOperations::move(other.inlineBuffer() + m_size, other.in lineBuffer() + other.m_size, inlineBuffer() + m_size); | |
465 } | 544 } |
466 } else if (buffer() == inlineBuffer()) { | 545 } |
467 m_buffer = other.m_buffer; | 546 |
468 other.m_buffer = other.inlineBuffer(); | 547 // Process the ranges from right to left. There are 0 to 2 ranges fo r |
469 TypeOperations::move(inlineBuffer(), inlineBuffer() + m_size, ot her.inlineBuffer()); | 548 // this vector buffer and 0 to 2 for the other. |
470 std::swap(m_capacity, other.m_capacity); | 549 while (thisRangePtr >= thisRanges || otherRangePtr >= otherRanges) { |
Ken Russell (switch to Gerrit)
2014/07/23 06:27:57
Thanks for giving this more thought. This does loo
Ken Russell (switch to Gerrit)
2014/07/29 00:15:32
Ping. Any progress on an over-the-shoulder review
Mads Ager (chromium)
2014/08/04 10:17:12
Overlapping vacations at play. ;-)
Erik and I dis
| |
471 } else if (other.buffer() == other.inlineBuffer()) { | 550 Range thisRange = thisRangePtr < thisRanges ? Range(0, 0) : *thi sRangePtr; |
472 other.m_buffer = m_buffer; | 551 Range otherRange = otherRangePtr < otherRanges ? Range(0, 0) : * otherRangePtr; |
473 m_buffer = inlineBuffer(); | 552 |
474 TypeOperations::move(other.inlineBuffer(), other.inlineBuffer() + other.m_size, inlineBuffer()); | 553 if (thisRange.end > otherRange.end) { |
475 std::swap(m_capacity, other.m_capacity); | 554 unsigned moveStart = std::max(thisRange.start, otherRange.en d); |
476 } else { | 555 TypeOperations::move(inlBuf + moveStart, inlBuf + thisRange. end, otherInlBuf + moveStart); |
477 std::swap(m_buffer, other.m_buffer); | 556 } else if (otherRange.end > thisRange.end) { |
478 std::swap(m_capacity, other.m_capacity); | 557 unsigned moveStart = std::max(otherRange.start, thisRange.en d); |
558 TypeOperations::move(otherInlBuf + moveStart, otherInlBuf + otherRange.end, inlBuf + moveStart); | |
559 } | |
560 | |
561 if (thisRange.start >= otherRange.end) { | |
562 thisRangePtr--; | |
563 } else if (otherRange.start >= thisRange.end) { | |
564 otherRangePtr--; | |
565 } else { | |
566 thisRangePtr--; | |
567 otherRangePtr--; | |
568 // Rightmost ranges overlap. We already moved any overhang, above. | |
569 unsigned startOfOverlap = std::max(thisRange.start, otherRan ge.start); | |
570 unsigned endOfOverlap = std::min(thisRange.end, otherRange.e nd); | |
571 TypeOperations::swap(inlBuf + startOfOverlap, inlBuf + endOf Overlap, otherInlBuf + startOfOverlap); | |
572 // One of the ranges may extend to the left of the overlap, | |
573 // in which case we have a new range to the left of that | |
574 // overlap. | |
575 if (thisRange.start < otherRange.start) { | |
576 *++thisRangePtr = Range(thisRange.start, startOfOverlap) ; | |
577 } else if (otherRange.start < thisRange.start) { | |
578 *++otherRangePtr = Range(otherRange.start, startOfOverla p); | |
579 } | |
580 } | |
479 } | 581 } |
480 } | 582 } |
481 | 583 |
482 using Base::buffer; | 584 using Base::buffer; |
483 using Base::capacity; | 585 using Base::capacity; |
586 using Base::findRanges; | |
484 | 587 |
485 bool hasOutOfLineBuffer() const | 588 bool hasOutOfLineBuffer() const |
486 { | 589 { |
487 return buffer() && buffer() != inlineBuffer(); | 590 return buffer() && buffer() != inlineBuffer(); |
488 } | 591 } |
489 | 592 |
490 protected: | |
491 using Base::m_size; | |
492 | |
493 private: | 593 private: |
494 using Base::m_buffer; | 594 using Base::m_buffer; |
495 using Base::m_capacity; | 595 using Base::m_capacity; |
496 | 596 |
497 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); | 597 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); |
498 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffe r); } | 598 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffe r); } |
499 const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_ inlineBuffer.buffer); } | 599 const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_ inlineBuffer.buffer); } |
500 | 600 |
501 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; | 601 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; |
502 template<typename U, size_t inlineBuffer, typename V> | 602 template<typename U, size_t inlineBuffer, typename V> |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
543 | 643 |
544 template<typename Derived, typename Elements> | 644 template<typename Derived, typename Elements> |
545 class VectorDestructorBase<Derived, Elements, true, true> : public HeapVecto rWithInlineCapacityDestructorBase<Derived, VectorTraits<Elements>::needsDestruct ion> { }; | 645 class VectorDestructorBase<Derived, Elements, true, true> : public HeapVecto rWithInlineCapacityDestructorBase<Derived, VectorTraits<Elements>::needsDestruct ion> { }; |
546 | 646 |
547 template<typename T, size_t inlineCapacity = 0, typename Allocator = Default Allocator> | 647 template<typename T, size_t inlineCapacity = 0, typename Allocator = Default Allocator> |
548 class Vector : private VectorBuffer<T, inlineCapacity, Allocator>, public Ve ctorDestructorBase<Vector<T, inlineCapacity, Allocator>, T, (inlineCapacity > 0) , Allocator::isGarbageCollected> { | 648 class Vector : private VectorBuffer<T, inlineCapacity, Allocator>, public Ve ctorDestructorBase<Vector<T, inlineCapacity, Allocator>, T, (inlineCapacity > 0) , Allocator::isGarbageCollected> { |
549 WTF_USE_ALLOCATOR(Vector, Allocator); | 649 WTF_USE_ALLOCATOR(Vector, Allocator); |
550 private: | 650 private: |
551 typedef VectorBuffer<T, inlineCapacity, Allocator> Base; | 651 typedef VectorBuffer<T, inlineCapacity, Allocator> Base; |
552 typedef VectorTypeOperations<T> TypeOperations; | 652 typedef VectorTypeOperations<T> TypeOperations; |
653 typedef typename Base::Range Range; | |
553 | 654 |
554 public: | 655 public: |
555 typedef T ValueType; | 656 typedef T ValueType; |
556 | 657 |
557 typedef T* iterator; | 658 typedef T* iterator; |
558 typedef const T* const_iterator; | 659 typedef const T* const_iterator; |
559 typedef std::reverse_iterator<iterator> reverse_iterator; | 660 typedef std::reverse_iterator<iterator> reverse_iterator; |
560 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | 661 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
561 | 662 |
562 Vector() | 663 Vector() |
664 : m_size(0) | |
563 { | 665 { |
564 // Unused slots are initialized to zero so that the visitor and the | 666 // Unused slots are initialized to zero so that the visitor and the |
565 // finalizer can visit them safely. canInitializeWithMemset tells us | 667 // finalizer can visit them safely. canInitializeWithMemset tells us |
566 // that the class does not expect matching constructor and | 668 // that the class does not expect matching constructor and |
567 // destructor calls as long as the memory is zeroed. | 669 // destructor calls as long as the memory is zeroed. |
568 COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::n eedsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWit hFinalizersCalledOnClearedMemory); | 670 COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::n eedsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWit hFinalizersCalledOnClearedMemory); |
569 COMPILE_ASSERT(!WTF::IsPolymorphic<T>::value || !VectorTraits<T>::ca nInitializeWithMemset, CantInitializeWithMemsetIfThereIsAVtable); | 671 COMPILE_ASSERT(!WTF::IsPolymorphic<T>::value || !VectorTraits<T>::ca nInitializeWithMemset, CantInitializeWithMemsetIfThereIsAVtable); |
570 m_size = 0; | |
571 } | 672 } |
572 | 673 |
573 explicit Vector(size_t size) | 674 explicit Vector(size_t size) |
574 : Base(size) | 675 : Base(size) |
575 { | 676 { |
677 setSize(size); | |
576 // Unused slots are initialized to zero so that the visitor and the | 678 // Unused slots are initialized to zero so that the visitor and the |
577 // finalizer can visit them safely. canInitializeWithMemset tells us | 679 // finalizer can visit them safely. canInitializeWithMemset tells us |
578 // that the class does not expect matching constructor and | 680 // that the class does not expect matching constructor and |
579 // destructor calls as long as the memory is zeroed. | 681 // destructor calls as long as the memory is zeroed. |
580 COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::n eedsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWit hFinalizersCalledOnClearedMemory); | 682 COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::n eedsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWit hFinalizersCalledOnClearedMemory); |
581 m_size = size; | |
582 TypeOperations::initialize(begin(), end()); | 683 TypeOperations::initialize(begin(), end()); |
583 } | 684 } |
584 | 685 |
585 // Off-GC-heap vectors: Destructor should be called. | 686 // Off-GC-heap vectors: Destructor should be called. |
586 // On-GC-heap vectors: Destructor should be called for inline buffers | 687 // On-GC-heap vectors: Destructor should be called for inline buffers |
587 // (if any) but destructor shouldn't be called for vector backing since | 688 // (if any) but destructor shouldn't be called for vector backing since |
588 // it is managed by the traced GC heap. | 689 // it is managed by the traced GC heap. |
589 void finalize() | 690 void finalize() |
590 { | 691 { |
591 if (!inlineCapacity) { | 692 if (!inlineCapacity) { |
592 if (LIKELY(!Base::buffer())) | 693 if (LIKELY(!Base::buffer())) |
593 return; | 694 return; |
594 } | 695 } |
595 if (LIKELY(m_size) && !(Allocator::isGarbageCollected && this->hasOu tOfLineBuffer())) { | 696 if (LIKELY(size()) && !(Allocator::isGarbageCollected && this->hasOu tOfLineBuffer())) { |
596 TypeOperations::destruct(begin(), end()); | 697 TypeOperations::destruct(begin(), end()); |
597 m_size = 0; // Partial protection against use-after-free. | 698 setSize(0); // Partial protection against use-after-free. |
598 } | 699 } |
599 | 700 |
600 Base::destruct(); | 701 Base::destruct(); |
601 } | 702 } |
602 | 703 |
603 void finalizeGarbageCollectedObject() | 704 void finalizeGarbageCollectedObject() |
604 { | 705 { |
605 finalize(); | 706 finalize(); |
606 } | 707 } |
607 | 708 |
608 Vector(const Vector&); | 709 Vector(const Vector&); |
609 template<size_t otherCapacity> | 710 template<size_t otherInlineCapacity> |
610 explicit Vector(const Vector<T, otherCapacity, Allocator>&); | 711 explicit Vector(const Vector<T, otherInlineCapacity, Allocator>&); |
611 | 712 |
612 Vector& operator=(const Vector&); | 713 Vector& operator=(const Vector&); |
613 template<size_t otherCapacity> | 714 template<size_t otherInlineCapacity> |
614 Vector& operator=(const Vector<T, otherCapacity, Allocator>&); | 715 Vector& operator=(const Vector<T, otherInlineCapacity, Allocator>&); |
615 | 716 |
616 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) | 717 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) |
617 Vector(Vector&&); | 718 Vector(Vector&&); |
618 Vector& operator=(Vector&&); | 719 Vector& operator=(Vector&&); |
619 #endif | 720 #endif |
620 | 721 |
621 size_t size() const { return m_size; } | |
622 size_t capacity() const { return Base::capacity(); } | 722 size_t capacity() const { return Base::capacity(); } |
623 bool isEmpty() const { return !size(); } | 723 bool isEmpty() const { return !size(); } |
624 | 724 |
625 T& at(size_t i) | 725 T& at(size_t i) |
626 { | 726 { |
627 RELEASE_ASSERT(i < size()); | 727 RELEASE_ASSERT(i < size()); |
628 return Base::buffer()[i]; | 728 return Base::buffer()[i]; |
629 } | 729 } |
630 const T& at(size_t i) const | 730 const T& at(size_t i) const |
631 { | 731 { |
632 RELEASE_ASSERT(i < size()); | 732 RELEASE_ASSERT(i < size()); |
633 return Base::buffer()[i]; | 733 return Base::buffer()[i]; |
634 } | 734 } |
635 | 735 |
636 T& operator[](size_t i) { return at(i); } | 736 T& operator[](size_t i) { return at(i); } |
637 const T& operator[](size_t i) const { return at(i); } | 737 const T& operator[](size_t i) const { return at(i); } |
638 | 738 |
639 T* data() { return Base::buffer(); } | 739 T* data() { return Base::buffer(); } |
640 const T* data() const { return Base::buffer(); } | 740 const T* data() const { return Base::buffer(); } |
641 | 741 |
642 iterator begin() { return data(); } | 742 iterator begin() { return data(); } |
643 iterator end() { return begin() + m_size; } | 743 iterator end() { return begin() + size(); } |
644 const_iterator begin() const { return data(); } | 744 const_iterator begin() const { return data(); } |
645 const_iterator end() const { return begin() + m_size; } | 745 const_iterator end() const { return begin() + size(); } |
646 | 746 |
647 reverse_iterator rbegin() { return reverse_iterator(end()); } | 747 reverse_iterator rbegin() { return reverse_iterator(end()); } |
648 reverse_iterator rend() { return reverse_iterator(begin()); } | 748 reverse_iterator rend() { return reverse_iterator(begin()); } |
649 const_reverse_iterator rbegin() const { return const_reverse_iterator(en d()); } | 749 const_reverse_iterator rbegin() const { return const_reverse_iterator(en d()); } |
650 const_reverse_iterator rend() const { return const_reverse_iterator(begi n()); } | 750 const_reverse_iterator rend() const { return const_reverse_iterator(begi n()); } |
651 | 751 |
652 T& first() { return at(0); } | 752 T& first() { return at(0); } |
653 const T& first() const { return at(0); } | 753 const T& first() const { return at(0); } |
654 T& last() { return at(size() - 1); } | 754 T& last() { return at(size() - 1); } |
655 const T& last() const { return at(size() - 1); } | 755 const T& last() const { return at(size() - 1); } |
(...skipping 12 matching lines...) Expand all Loading... | |
668 { | 768 { |
669 if (size() * 2 < capacity()) | 769 if (size() * 2 < capacity()) |
670 shrinkCapacity(size() + size() / 4 + 1); | 770 shrinkCapacity(size() + size() / 4 + 1); |
671 } | 771 } |
672 | 772 |
673 void clear() { shrinkCapacity(0); } | 773 void clear() { shrinkCapacity(0); } |
674 | 774 |
675 template<typename U> void append(const U*, size_t); | 775 template<typename U> void append(const U*, size_t); |
676 template<typename U> void append(const U&); | 776 template<typename U> void append(const U&); |
677 template<typename U> void uncheckedAppend(const U& val); | 777 template<typename U> void uncheckedAppend(const U& val); |
678 template<typename U, size_t otherCapacity, typename V> void appendVector (const Vector<U, otherCapacity, V>&); | 778 template<typename U, size_t otherInlineCapacity, typename V> void append Vector(const Vector<U, otherInlineCapacity, V>&); |
679 | 779 |
680 template<typename U> void insert(size_t position, const U*, size_t); | 780 template<typename U> void insert(size_t position, const U*, size_t); |
681 template<typename U> void insert(size_t position, const U&); | 781 template<typename U> void insert(size_t position, const U&); |
682 template<typename U, size_t c, typename V> void insert(size_t position, const Vector<U, c, V>&); | 782 template<typename U, size_t c, typename V> void insert(size_t position, const Vector<U, c, V>&); |
683 | 783 |
684 template<typename U> void prepend(const U*, size_t); | 784 template<typename U> void prepend(const U*, size_t); |
685 template<typename U> void prepend(const U&); | 785 template<typename U> void prepend(const U&); |
686 template<typename U, size_t c, typename V> void prepend(const Vector<U, c, V>&); | 786 template<typename U, size_t c, typename V> void prepend(const Vector<U, c, V>&); |
687 | 787 |
688 void remove(size_t position); | 788 void remove(size_t position); |
689 void remove(size_t position, size_t length); | 789 void remove(size_t position, size_t length); |
690 | 790 |
691 void removeLast() | 791 void removeLast() |
692 { | 792 { |
693 ASSERT(!isEmpty()); | 793 ASSERT(!isEmpty()); |
694 shrink(size() - 1); | 794 shrink(size() - 1); |
695 } | 795 } |
696 | 796 |
697 Vector(size_t size, const T& val) | 797 Vector(size_t size, const T& val) |
698 : Base(size) | 798 : Base(size) |
699 { | 799 { |
700 m_size = size; | 800 setSize(size); |
701 TypeOperations::uninitializedFill(begin(), end(), val); | 801 TypeOperations::uninitializedFill(begin(), end(), val); |
702 } | 802 } |
703 | 803 |
704 void fill(const T&, size_t); | 804 void fill(const T&, size_t); |
705 void fill(const T& val) { fill(val, size()); } | 805 void fill(const T& val) { fill(val, size()); } |
706 | 806 |
707 template<typename Iterator> void appendRange(Iterator start, Iterator en d); | 807 template<typename Iterator> void appendRange(Iterator start, Iterator en d); |
708 | 808 |
709 void swap(Vector& other) | 809 void swap(Vector& other); |
710 { | |
711 Base::swapVectorBuffer(other); | |
712 std::swap(m_size, other.m_size); | |
713 } | |
714 | 810 |
715 void reverse(); | 811 void reverse(); |
716 | 812 |
717 void trace(typename Allocator::Visitor*); | 813 void trace(typename Allocator::Visitor*); |
718 | 814 |
815 size_t size() const { return m_size; } | |
719 private: | 816 private: |
720 void expandCapacity(size_t newMinCapacity); | 817 void expandCapacity(size_t newMinCapacity); |
721 const T* expandCapacity(size_t newMinCapacity, const T*); | 818 const T* expandCapacity(size_t newMinCapacity, const T*); |
722 template<typename U> U* expandCapacity(size_t newMinCapacity, U*); | 819 template<typename U> U* expandCapacity(size_t newMinCapacity, U*); |
723 void shrinkCapacity(size_t newCapacity); | 820 void shrinkCapacity(size_t newCapacity); |
724 template<typename U> void appendSlowCase(const U&); | 821 template<typename U> void appendSlowCase(const U&); |
725 | 822 |
726 using Base::m_size; | 823 void setSize(unsigned size) |
824 { | |
825 m_size = size; | |
826 } | |
827 | |
828 unsigned m_size; | |
829 | |
727 using Base::buffer; | 830 using Base::buffer; |
728 using Base::capacity; | 831 using Base::capacity; |
729 using Base::swapVectorBuffer; | |
730 using Base::allocateBuffer; | 832 using Base::allocateBuffer; |
731 using Base::allocationSize; | 833 using Base::allocationSize; |
732 using Base::clearUnusedSlots; | 834 using Base::clearUnusedSlots; |
835 using Base::hasOutOfLineBuffer; | |
733 }; | 836 }; |
734 | 837 |
735 template<typename T, size_t inlineCapacity, typename Allocator> | 838 template<typename T, size_t inlineCapacity, typename Allocator> |
839 void Vector<T, inlineCapacity, Allocator>::swap(Vector<T, inlineCapacity, Al locator>& other) | |
840 { | |
841 Base::swapVectorBuffer(other, Range(0, m_size), Range(0, other.m_size)); | |
842 std::swap(m_size, other.m_size); | |
843 } | |
844 | |
845 template<typename T, size_t inlineCapacity, typename Allocator> | |
736 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) | 846 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) |
737 : Base(other.capacity()) | 847 : Base(other.capacity()) |
738 { | 848 { |
739 m_size = other.size(); | 849 setSize(other.size()); |
740 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); | 850 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
741 } | 851 } |
742 | 852 |
743 template<typename T, size_t inlineCapacity, typename Allocator> | 853 template<typename T, size_t inlineCapacity, typename Allocator> |
744 template<size_t otherCapacity> | 854 template<size_t otherInlineCapacity> |
745 Vector<T, inlineCapacity, Allocator>::Vector(const Vector<T, otherCapacity, Allocator>& other) | 855 Vector<T, inlineCapacity, Allocator>::Vector(const Vector<T, otherInlineCapa city, Allocator>& other) |
746 : Base(other.capacity()) | 856 : Base(other.capacity()) |
747 { | 857 { |
748 m_size = other.size(); | 858 setSize(other.size()); |
749 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); | 859 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
750 } | 860 } |
751 | 861 |
752 template<typename T, size_t inlineCapacity, typename Allocator> | 862 template<typename T, size_t inlineCapacity, typename Allocator> |
753 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, inlineCapacity, Allocator>& other) | 863 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, inlineCapacity, Allocator>& other) |
754 { | 864 { |
755 if (UNLIKELY(&other == this)) | 865 if (UNLIKELY(&other == this)) |
756 return *this; | 866 return *this; |
757 | 867 |
758 if (size() > other.size()) | 868 if (size() > other.size()) |
759 shrink(other.size()); | 869 shrink(other.size()); |
760 else if (other.size() > capacity()) { | 870 else if (other.size() > capacity()) { |
761 clear(); | 871 clear(); |
762 reserveCapacity(other.size()); | 872 reserveCapacity(other.size()); |
763 ASSERT(begin()); | 873 ASSERT(begin()); |
764 } | 874 } |
765 | 875 |
766 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStu dio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last | 876 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStu dio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last |
767 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL | 877 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL |
768 if (!begin()) | 878 if (!begin()) |
769 return *this; | 879 return *this; |
770 #endif | 880 #endif |
771 | 881 |
772 std::copy(other.begin(), other.begin() + size(), begin()); | 882 std::copy(other.begin(), other.begin() + size(), begin()); |
773 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); | 883 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); |
774 m_size = other.size(); | 884 setSize(other.size()); |
775 | 885 |
776 return *this; | 886 return *this; |
777 } | 887 } |
778 | 888 |
779 inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; } | 889 inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; } |
780 | 890 |
781 template<typename T, size_t inlineCapacity, typename Allocator> | 891 template<typename T, size_t inlineCapacity, typename Allocator> |
782 template<size_t otherCapacity> | 892 template<size_t otherInlineCapacity> |
783 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, otherCapacity, Allocator>& other) | 893 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, otherInlineCapacity, Allocator>& other) |
784 { | 894 { |
785 // If the inline capacities match, we should call the more specific | 895 // If the inline capacities match, we should call the more specific |
786 // template. If the inline capacities don't match, the two objects | 896 // template. If the inline capacities don't match, the two objects |
787 // shouldn't be allocated the same address. | 897 // shouldn't be allocated the same address. |
788 ASSERT(!typelessPointersAreEqual(&other, this)); | 898 ASSERT(!typelessPointersAreEqual(&other, this)); |
789 | 899 |
790 if (size() > other.size()) | 900 if (size() > other.size()) |
791 shrink(other.size()); | 901 shrink(other.size()); |
792 else if (other.size() > capacity()) { | 902 else if (other.size() > capacity()) { |
793 clear(); | 903 clear(); |
794 reserveCapacity(other.size()); | 904 reserveCapacity(other.size()); |
795 ASSERT(begin()); | 905 ASSERT(begin()); |
796 } | 906 } |
797 | 907 |
798 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStu dio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last | 908 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStu dio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last |
799 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL | 909 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL |
800 if (!begin()) | 910 if (!begin()) |
801 return *this; | 911 return *this; |
802 #endif | 912 #endif |
803 | 913 |
804 std::copy(other.begin(), other.begin() + size(), begin()); | 914 std::copy(other.begin(), other.begin() + size(), begin()); |
805 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); | 915 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); |
806 m_size = other.size(); | 916 setSize(other.size()); |
807 | 917 |
808 return *this; | 918 return *this; |
809 } | 919 } |
810 | 920 |
811 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) | 921 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) |
812 template<typename T, size_t inlineCapacity, typename Allocator> | 922 template<typename T, size_t inlineCapacity, typename Allocator> |
813 Vector<T, inlineCapacity, Allocator>::Vector(Vector<T, inlineCapacity, Alloc ator>&& other) | 923 Vector<T, inlineCapacity, Allocator>::Vector(Vector<T, inlineCapacity, Alloc ator>&& other) |
814 { | 924 { |
815 m_size = 0; | 925 setSize(0); |
816 // It's a little weird to implement a move constructor using swap but th is way we | 926 // It's a little weird to implement a move constructor using swap but th is way we |
817 // don't have to add a move constructor to VectorBuffer. | 927 // don't have to add a move constructor to VectorBuffer. |
818 swap(other); | 928 swap(other); |
819 } | 929 } |
820 | 930 |
821 template<typename T, size_t inlineCapacity, typename Allocator> | 931 template<typename T, size_t inlineCapacity, typename Allocator> |
822 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(Vector<T, inlineCapacity, Allocator>&& other) | 932 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(Vector<T, inlineCapacity, Allocator>&& other) |
823 { | 933 { |
824 swap(other); | 934 swap(other); |
825 return *this; | 935 return *this; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
866 if (size() > newSize) | 976 if (size() > newSize) |
867 shrink(newSize); | 977 shrink(newSize); |
868 else if (newSize > capacity()) { | 978 else if (newSize > capacity()) { |
869 clear(); | 979 clear(); |
870 reserveCapacity(newSize); | 980 reserveCapacity(newSize); |
871 ASSERT(begin()); | 981 ASSERT(begin()); |
872 } | 982 } |
873 | 983 |
874 std::fill(begin(), end(), val); | 984 std::fill(begin(), end(), val); |
875 TypeOperations::uninitializedFill(end(), begin() + newSize, val); | 985 TypeOperations::uninitializedFill(end(), begin() + newSize, val); |
876 m_size = newSize; | 986 setSize(newSize); |
877 } | 987 } |
878 | 988 |
879 template<typename T, size_t inlineCapacity, typename Allocator> | 989 template<typename T, size_t inlineCapacity, typename Allocator> |
880 template<typename Iterator> | 990 template<typename Iterator> |
881 void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start, Itera tor end) | 991 void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start, Itera tor end) |
882 { | 992 { |
883 for (Iterator it = start; it != end; ++it) | 993 for (Iterator it = start; it != end; ++it) |
884 append(*it); | 994 append(*it); |
885 } | 995 } |
886 | 996 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
919 } | 1029 } |
920 | 1030 |
921 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1031 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
922 inline U* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMin Capacity, U* ptr) | 1032 inline U* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMin Capacity, U* ptr) |
923 { | 1033 { |
924 expandCapacity(newMinCapacity); | 1034 expandCapacity(newMinCapacity); |
925 return ptr; | 1035 return ptr; |
926 } | 1036 } |
927 | 1037 |
928 template<typename T, size_t inlineCapacity, typename Allocator> | 1038 template<typename T, size_t inlineCapacity, typename Allocator> |
929 inline void Vector<T, inlineCapacity, Allocator>::resize(size_t size) | 1039 inline void Vector<T, inlineCapacity, Allocator>::resize(size_t sizeArg) |
Mikhail
2014/07/23 10:02:47
AFAIK 'Arg' postfix is mostly used for template ar
| |
930 { | 1040 { |
931 if (size <= m_size) | 1041 if (sizeArg <= size()) |
932 TypeOperations::destruct(begin() + size, end()); | 1042 TypeOperations::destruct(begin() + sizeArg, end()); |
933 else { | 1043 else { |
934 if (size > capacity()) | 1044 if (sizeArg > capacity()) |
935 expandCapacity(size); | 1045 expandCapacity(sizeArg); |
936 TypeOperations::initialize(end(), begin() + size); | 1046 TypeOperations::initialize(end(), begin() + sizeArg); |
937 } | 1047 } |
938 | 1048 |
939 m_size = size; | 1049 setSize(sizeArg); |
940 } | 1050 } |
941 | 1051 |
942 template<typename T, size_t inlineCapacity, typename Allocator> | 1052 template<typename T, size_t inlineCapacity, typename Allocator> |
943 void Vector<T, inlineCapacity, Allocator>::shrink(size_t size) | 1053 void Vector<T, inlineCapacity, Allocator>::shrink(size_t sizeArg) |
944 { | 1054 { |
945 ASSERT(size <= m_size); | 1055 ASSERT(sizeArg <= size()); |
946 TypeOperations::destruct(begin() + size, end()); | 1056 TypeOperations::destruct(begin() + sizeArg, end()); |
947 clearUnusedSlots(begin() + size, end()); | 1057 clearUnusedSlots(begin() + sizeArg, end()); |
948 m_size = size; | 1058 setSize(sizeArg); |
949 } | 1059 } |
950 | 1060 |
951 template<typename T, size_t inlineCapacity, typename Allocator> | 1061 template<typename T, size_t inlineCapacity, typename Allocator> |
952 void Vector<T, inlineCapacity, Allocator>::grow(size_t size) | 1062 void Vector<T, inlineCapacity, Allocator>::grow(size_t sizeArg) |
953 { | 1063 { |
954 ASSERT(size >= m_size); | 1064 ASSERT(sizeArg >= size()); |
955 if (size > capacity()) | 1065 if (sizeArg > capacity()) |
956 expandCapacity(size); | 1066 expandCapacity(sizeArg); |
957 TypeOperations::initialize(end(), begin() + size); | 1067 TypeOperations::initialize(end(), begin() + sizeArg); |
958 m_size = size; | 1068 setSize(sizeArg); |
959 } | 1069 } |
960 | 1070 |
961 template<typename T, size_t inlineCapacity, typename Allocator> | 1071 template<typename T, size_t inlineCapacity, typename Allocator> |
962 void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacit y) | 1072 void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacit y) |
963 { | 1073 { |
964 if (UNLIKELY(newCapacity <= capacity())) | 1074 if (UNLIKELY(newCapacity <= capacity())) |
965 return; | 1075 return; |
966 T* oldBuffer = begin(); | 1076 T* oldBuffer = begin(); |
967 T* oldEnd = end(); | 1077 T* oldEnd = end(); |
968 Base::allocateBuffer(newCapacity); | 1078 Base::allocateBuffer(newCapacity); |
969 TypeOperations::move(oldBuffer, oldEnd, begin()); | 1079 TypeOperations::move(oldBuffer, oldEnd, begin()); |
970 Base::deallocateBuffer(oldBuffer); | 1080 Base::deallocateBuffer(oldBuffer); |
971 } | 1081 } |
972 | 1082 |
973 template<typename T, size_t inlineCapacity, typename Allocator> | 1083 template<typename T, size_t inlineCapacity, typename Allocator> |
974 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(siz e_t initialCapacity) | 1084 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(siz e_t initialCapacity) |
975 { | 1085 { |
976 ASSERT(!m_size); | 1086 ASSERT(!size()); |
977 ASSERT(capacity() == inlineCapacity); | 1087 ASSERT(capacity() == inlineCapacity); |
978 if (initialCapacity > inlineCapacity) | 1088 if (initialCapacity > inlineCapacity) |
979 Base::allocateBuffer(initialCapacity); | 1089 Base::allocateBuffer(initialCapacity); |
980 } | 1090 } |
981 | 1091 |
982 template<typename T, size_t inlineCapacity, typename Allocator> | 1092 template<typename T, size_t inlineCapacity, typename Allocator> |
983 void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity ) | 1093 void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity ) |
984 { | 1094 { |
985 if (newCapacity >= capacity()) | 1095 if (newCapacity >= capacity()) |
986 return; | 1096 return; |
(...skipping 18 matching lines...) Expand all Loading... | |
1005 Base::deallocateBuffer(oldBuffer); | 1115 Base::deallocateBuffer(oldBuffer); |
1006 } | 1116 } |
1007 | 1117 |
1008 // Templatizing these is better than just letting the conversion happen impl icitly, | 1118 // Templatizing these is better than just letting the conversion happen impl icitly, |
1009 // because for instance it allows a PassRefPtr to be appended to a RefPtr ve ctor | 1119 // because for instance it allows a PassRefPtr to be appended to a RefPtr ve ctor |
1010 // without refcount thrash. | 1120 // without refcount thrash. |
1011 | 1121 |
1012 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1122 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1013 void Vector<T, inlineCapacity, Allocator>::append(const U* data, size_t data Size) | 1123 void Vector<T, inlineCapacity, Allocator>::append(const U* data, size_t data Size) |
1014 { | 1124 { |
1015 size_t newSize = m_size + dataSize; | 1125 size_t newSize = size() + dataSize; |
1016 if (newSize > capacity()) { | 1126 if (newSize > capacity()) { |
1017 data = expandCapacity(newSize, data); | 1127 data = expandCapacity(newSize, data); |
1018 ASSERT(begin()); | 1128 ASSERT(begin()); |
1019 } | 1129 } |
1020 RELEASE_ASSERT(newSize >= m_size); | 1130 RELEASE_ASSERT(newSize >= size()); |
1021 T* dest = end(); | 1131 T* dest = end(); |
1022 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], dest); | 1132 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], dest); |
1023 m_size = newSize; | 1133 setSize(newSize); |
1024 } | 1134 } |
1025 | 1135 |
1026 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1136 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1027 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val ) | 1137 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val ) |
1028 { | 1138 { |
1029 if (LIKELY(size() != capacity())) { | 1139 if (LIKELY(size() != capacity())) { |
1030 new (NotNull, end()) T(val); | 1140 new (NotNull, end()) T(val); |
1031 ++m_size; | 1141 setSize(size() + 1); |
1032 return; | 1142 return; |
1033 } | 1143 } |
1034 | 1144 |
1035 appendSlowCase(val); | 1145 appendSlowCase(val); |
1036 } | 1146 } |
1037 | 1147 |
1038 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1148 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1039 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U& val) | 1149 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U& val) |
1040 { | 1150 { |
1041 ASSERT(size() == capacity()); | 1151 ASSERT(size() == capacity()); |
1042 | 1152 |
1043 const U* ptr = &val; | 1153 const U* ptr = &val; |
1044 ptr = expandCapacity(size() + 1, ptr); | 1154 ptr = expandCapacity(size() + 1, ptr); |
1045 ASSERT(begin()); | 1155 ASSERT(begin()); |
1046 | 1156 |
1047 new (NotNull, end()) T(*ptr); | 1157 new (NotNull, end()) T(*ptr); |
1048 ++m_size; | 1158 setSize(size() + 1); |
1049 } | 1159 } |
1050 | 1160 |
1051 // This version of append saves a branch in the case where you know that the | 1161 // This version of append saves a branch in the case where you know that the |
1052 // vector's capacity is large enough for the append to succeed. | 1162 // vector's capacity is large enough for the append to succeed. |
1053 | 1163 |
1054 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1164 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1055 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(con st U& val) | 1165 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(con st U& val) |
1056 { | 1166 { |
1057 ASSERT(size() < capacity()); | 1167 ASSERT(size() < capacity()); |
1058 const U* ptr = &val; | 1168 const U* ptr = &val; |
1059 new (NotNull, end()) T(*ptr); | 1169 new (NotNull, end()) T(*ptr); |
1060 ++m_size; | 1170 setSize(size() + 1); |
1061 } | 1171 } |
1062 | 1172 |
1063 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U, size_t otherCapacity, typename OtherAllocator> | 1173 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U, size_t otherInlineCapacity, typename OtherAllocator> |
1064 inline void Vector<T, inlineCapacity, Allocator>::appendVector(const Vector< U, otherCapacity, OtherAllocator>& val) | 1174 inline void Vector<T, inlineCapacity, Allocator>::appendVector(const Vector< U, otherInlineCapacity, OtherAllocator>& val) |
1065 { | 1175 { |
1066 append(val.begin(), val.size()); | 1176 append(val.begin(), val.size()); |
1067 } | 1177 } |
1068 | 1178 |
1069 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1179 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1070 void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U* data, size_t dataSize) | 1180 void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U* data, size_t dataSize) |
1071 { | 1181 { |
1072 RELEASE_ASSERT(position <= size()); | 1182 RELEASE_ASSERT(position <= size()); |
1073 size_t newSize = m_size + dataSize; | 1183 size_t newSize = size() + dataSize; |
1074 if (newSize > capacity()) { | 1184 if (newSize > capacity()) { |
1075 data = expandCapacity(newSize, data); | 1185 data = expandCapacity(newSize, data); |
1076 ASSERT(begin()); | 1186 ASSERT(begin()); |
1077 } | 1187 } |
1078 RELEASE_ASSERT(newSize >= m_size); | 1188 RELEASE_ASSERT(newSize >= size()); |
1079 T* spot = begin() + position; | 1189 T* spot = begin() + position; |
1080 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); | 1190 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); |
1081 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], spot); | 1191 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], spot); |
1082 m_size = newSize; | 1192 setSize(newSize); |
1083 } | 1193 } |
1084 | 1194 |
1085 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1195 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1086 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, co nst U& val) | 1196 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, co nst U& val) |
1087 { | 1197 { |
1088 RELEASE_ASSERT(position <= size()); | 1198 RELEASE_ASSERT(position <= size()); |
1089 const U* data = &val; | 1199 const U* data = &val; |
1090 if (size() == capacity()) { | 1200 if (size() == capacity()) { |
1091 data = expandCapacity(size() + 1, data); | 1201 data = expandCapacity(size() + 1, data); |
1092 ASSERT(begin()); | 1202 ASSERT(begin()); |
1093 } | 1203 } |
1094 T* spot = begin() + position; | 1204 T* spot = begin() + position; |
1095 TypeOperations::moveOverlapping(spot, end(), spot + 1); | 1205 TypeOperations::moveOverlapping(spot, end(), spot + 1); |
1096 new (NotNull, spot) T(*data); | 1206 new (NotNull, spot) T(*data); |
1097 ++m_size; | 1207 setSize(size() + 1); |
1098 } | 1208 } |
1099 | 1209 |
1100 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U, size_t c, typename OtherAllocator> | 1210 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U, size_t c, typename OtherAllocator> |
1101 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, co nst Vector<U, c, OtherAllocator>& val) | 1211 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, co nst Vector<U, c, OtherAllocator>& val) |
1102 { | 1212 { |
1103 insert(position, val.begin(), val.size()); | 1213 insert(position, val.begin(), val.size()); |
1104 } | 1214 } |
1105 | 1215 |
1106 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1216 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
1107 void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, size_t dat aSize) | 1217 void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, size_t dat aSize) |
(...skipping 14 matching lines...) Expand all Loading... | |
1122 } | 1232 } |
1123 | 1233 |
1124 template<typename T, size_t inlineCapacity, typename Allocator> | 1234 template<typename T, size_t inlineCapacity, typename Allocator> |
1125 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) | 1235 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) |
1126 { | 1236 { |
1127 RELEASE_ASSERT(position < size()); | 1237 RELEASE_ASSERT(position < size()); |
1128 T* spot = begin() + position; | 1238 T* spot = begin() + position; |
1129 spot->~T(); | 1239 spot->~T(); |
1130 TypeOperations::moveOverlapping(spot + 1, end(), spot); | 1240 TypeOperations::moveOverlapping(spot + 1, end(), spot); |
1131 clearUnusedSlots(end() - 1, end()); | 1241 clearUnusedSlots(end() - 1, end()); |
1132 --m_size; | 1242 setSize(size() - 1); |
1133 } | 1243 } |
1134 | 1244 |
1135 template<typename T, size_t inlineCapacity, typename Allocator> | 1245 template<typename T, size_t inlineCapacity, typename Allocator> |
1136 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position, si ze_t length) | 1246 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position, si ze_t length) |
1137 { | 1247 { |
1138 ASSERT_WITH_SECURITY_IMPLICATION(position <= size()); | 1248 ASSERT_WITH_SECURITY_IMPLICATION(position <= size()); |
1139 RELEASE_ASSERT(position + length <= size()); | 1249 RELEASE_ASSERT(position + length <= size()); |
1140 T* beginSpot = begin() + position; | 1250 T* beginSpot = begin() + position; |
1141 T* endSpot = beginSpot + length; | 1251 T* endSpot = beginSpot + length; |
1142 TypeOperations::destruct(beginSpot, endSpot); | 1252 TypeOperations::destruct(beginSpot, endSpot); |
1143 TypeOperations::moveOverlapping(endSpot, end(), beginSpot); | 1253 TypeOperations::moveOverlapping(endSpot, end(), beginSpot); |
1144 clearUnusedSlots(end() - length, end()); | 1254 clearUnusedSlots(end() - length, end()); |
1145 m_size -= length; | 1255 setSize(size() - length); |
1146 } | 1256 } |
1147 | 1257 |
1148 template<typename T, size_t inlineCapacity, typename Allocator> | 1258 template<typename T, size_t inlineCapacity, typename Allocator> |
1149 inline void Vector<T, inlineCapacity, Allocator>::reverse() | 1259 inline void Vector<T, inlineCapacity, Allocator>::reverse() |
1150 { | 1260 { |
1151 for (size_t i = 0; i < m_size / 2; ++i) | 1261 for (size_t i = 0; i < size() / 2; ++i) |
1152 std::swap(at(i), at(m_size - 1 - i)); | 1262 std::swap(at(i), at(size() - 1 - i)); |
1153 } | 1263 } |
1154 | 1264 |
1155 template<typename T, size_t inlineCapacity, typename Allocator> | 1265 template<typename T, size_t inlineCapacity, typename Allocator> |
1156 void deleteAllValues(const Vector<T, inlineCapacity, Allocator>& collection) | 1266 void deleteAllValues(const Vector<T, inlineCapacity, Allocator>& collection) |
1157 { | 1267 { |
1158 typedef typename Vector<T, inlineCapacity, Allocator>::const_iterator it erator; | 1268 typedef typename Vector<T, inlineCapacity, Allocator>::const_iterator it erator; |
1159 iterator end = collection.end(); | 1269 iterator end = collection.end(); |
1160 for (iterator it = collection.begin(); it != end; ++it) | 1270 for (iterator it = collection.begin(); it != end; ++it) |
1161 delete *it; | 1271 delete *it; |
1162 } | 1272 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1203 struct NeedsTracing<Vector<T, N> > { | 1313 struct NeedsTracing<Vector<T, N> > { |
1204 static const bool value = false; | 1314 static const bool value = false; |
1205 }; | 1315 }; |
1206 #endif | 1316 #endif |
1207 | 1317 |
1208 } // namespace WTF | 1318 } // namespace WTF |
1209 | 1319 |
1210 using WTF::Vector; | 1320 using WTF::Vector; |
1211 | 1321 |
1212 #endif // WTF_Vector_h | 1322 #endif // WTF_Vector_h |
OLD | NEW |