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

Side by Side Diff: Source/wtf/Vector.h

Issue 390983010: Fix Deque.swap for deques with inline capacity Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Address comments from Ken and Mads, and simplify Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« Source/wtf/Deque.h ('K') | « Source/wtf/DequeTest.cpp ('k') | Source/wtf/VectorTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698