Chromium Code Reviews| 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); | |
| 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 { | |
| 333 Range(unsigned s = 0, unsigned e = 0) | |
| 334 : start(s) | |
| 335 , end(e) | |
| 336 { | |
| 337 } | |
| 338 | |
| 339 bool IsEmpty() { return start == end; } | |
| 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 // element past the last one. | |
| 348 Range* findRanges(Range* buffer, const Range in, unsigned capacity) | |
| 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; | |
| 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 void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other, Range thisRange, Range otherRange) |
|
Ken Russell (switch to Gerrit)
2014/07/16 07:38:42
Are the changes to this method tested sufficiently
Erik Corry
2014/07/17 14:44:33
More tests added
| |
| 454 { | 494 { |
| 455 typedef VectorTypeOperations<T> TypeOperations; | 495 typedef VectorTypeOperations<T> TypeOperations; |
| 456 | 496 |
| 457 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuff er()) { | 497 Range thisRanges[2]; |
| 458 ASSERT(m_capacity == other.m_capacity); | 498 Range otherRanges[2]; |
| 459 if (m_size > other.m_size) { | 499 Range* thisRangePtr = thisRanges; |
| 460 TypeOperations::swap(inlineBuffer(), inlineBuffer() + other. m_size, other.inlineBuffer()); | 500 Range* otherRangePtr = otherRanges; |
| 461 TypeOperations::move(inlineBuffer() + other.m_size, inlineBu ffer() + m_size, other.inlineBuffer() + other.m_size); | 501 |
| 502 std::swap(m_capacity, other.m_capacity); | |
| 503 if (buffer() != inlineBuffer() && other.buffer() != other.inlineBuff er()) { | |
| 504 std::swap(m_buffer, other.m_buffer); | |
| 505 } else { | |
| 506 T* otherBuffer = other.m_buffer; | |
| 507 if (buffer() == inlineBuffer()) { | |
| 508 thisRangePtr = findRanges(thisRanges, thisRange, inlineCapac ity); | |
| 462 } else { | 509 } else { |
| 463 TypeOperations::swap(inlineBuffer(), inlineBuffer() + m_size , other.inlineBuffer()); | 510 other.m_buffer = m_buffer; |
| 464 TypeOperations::move(other.inlineBuffer() + m_size, other.in lineBuffer() + other.m_size, inlineBuffer() + m_size); | 511 m_buffer = inlineBuffer(); |
| 465 } | 512 } |
| 466 } else if (buffer() == inlineBuffer()) { | 513 if (otherBuffer == other.inlineBuffer()) { |
| 467 m_buffer = other.m_buffer; | 514 otherRangePtr = findRanges(otherRanges, otherRange, inlineCa pacity); |
| 468 other.m_buffer = other.inlineBuffer(); | 515 } else { |
| 469 TypeOperations::move(inlineBuffer(), inlineBuffer() + m_size, ot her.inlineBuffer()); | 516 m_buffer = otherBuffer; |
| 470 std::swap(m_capacity, other.m_capacity); | 517 other.m_buffer = other.inlineBuffer(); |
| 471 } else if (other.buffer() == other.inlineBuffer()) { | 518 } |
| 472 other.m_buffer = m_buffer; | 519 } |
| 473 m_buffer = inlineBuffer(); | 520 |
| 474 TypeOperations::move(other.inlineBuffer(), other.inlineBuffer() + other.m_size, inlineBuffer()); | 521 while (thisRangePtr != thisRanges || otherRangePtr != otherRanges) { |
| 475 std::swap(m_capacity, other.m_capacity); | 522 if (thisRangePtr == thisRanges) { |
| 476 } else { | 523 // Ran out of ranges in this: process a range in the other. |
| 477 std::swap(m_buffer, other.m_buffer); | 524 Range otherRange = *--otherRangePtr; |
| 478 std::swap(m_capacity, other.m_capacity); | 525 TypeOperations::move(other.inlineBuffer() + otherRange.start , other.inlineBuffer() + otherRange.end, inlineBuffer() + otherRange.start); |
| 526 continue; | |
| 527 } | |
| 528 if (otherRangePtr == otherRanges) { | |
| 529 // Ran out of ranges in the other: process a range in this. | |
| 530 Range thisRange = *--thisRangePtr; | |
| 531 TypeOperations::move(inlineBuffer() + thisRange.start, inlin eBuffer() + thisRange.end, other.inlineBuffer() + thisRange.start); | |
| 532 continue; | |
| 533 } | |
| 534 // We have a rightmost range in both. Find out which extends fur thest to the right. | |
| 535 Range otherRange = *--otherRangePtr; | |
| 536 Range thisRange = *--thisRangePtr; | |
| 537 if (otherRange.end == thisRange.end) { | |
| 538 // They end together: Find the start of the overlap. | |
| 539 unsigned startOfOverlap = std::max(thisRange.start, otherRan ge.start); | |
| 540 TypeOperations::swap(inlineBuffer() + startOfOverlap, inline Buffer() + thisRange.end, other.inlineBuffer() + startOfOverlap); | |
| 541 if (otherRange.start == thisRange.start) | |
| 542 continue; // Common left edge - we are done with these e ntries. | |
| 543 if (otherRange.start < thisRange.start) { | |
| 544 // The other extends further to the left, make a new ran ge. | |
| 545 *otherRangePtr++ = Range(otherRange.start, thisRange.sta rt); | |
| 546 continue; | |
| 547 } | |
| 548 // This extends further to the left, make a new range. | |
| 549 *thisRangePtr++ = Range(thisRange.start, otherRange.start); | |
| 550 continue; | |
| 551 } | |
| 552 if (otherRange.end > thisRange.end) { | |
| 553 // Other one hangs over the edge. | |
| 554 unsigned startOfOverhang = std::max(otherRange.start, thisRa nge.end); | |
| 555 TypeOperations::move(other.inlineBuffer() + startOfOverhang, other.inlineBuffer() + otherRange.end, inlineBuffer() + startOfOverhang); | |
| 556 if (otherRange.start != startOfOverhang) | |
| 557 *otherRangePtr++ = Range(otherRange.start, startOfOverha ng); | |
| 558 *thisRangePtr++ = thisRange; | |
| 559 continue; | |
| 560 } | |
| 561 ASSERT(thisRange.end > otherRange.end); | |
| 562 // This one hangs over the edge. | |
| 563 unsigned startOfOverhang = std::max(thisRange.start, otherRange. end); | |
| 564 TypeOperations::move(inlineBuffer() + startOfOverhang, inlineBuf fer() + thisRange.end, other.inlineBuffer() + startOfOverhang); | |
| 565 if (thisRange.start != startOfOverhang) | |
| 566 *thisRangePtr++ = Range(thisRange.start, startOfOverhang); | |
| 567 *otherRangePtr++ = otherRange; | |
| 479 } | 568 } |
| 480 } | 569 } |
| 481 | 570 |
| 482 using Base::buffer; | 571 using Base::buffer; |
| 483 using Base::capacity; | 572 using Base::capacity; |
| 573 using Base::findRanges; | |
| 484 | 574 |
| 485 bool hasOutOfLineBuffer() const | 575 bool hasOutOfLineBuffer() const |
| 486 { | 576 { |
| 487 return buffer() && buffer() != inlineBuffer(); | 577 return buffer() && buffer() != inlineBuffer(); |
| 488 } | 578 } |
| 489 | 579 |
| 490 protected: | |
| 491 using Base::m_size; | |
| 492 | |
| 493 private: | 580 private: |
| 494 using Base::m_buffer; | 581 using Base::m_buffer; |
| 495 using Base::m_capacity; | 582 using Base::m_capacity; |
| 496 | 583 |
| 497 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); | 584 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); |
| 498 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffe r); } | 585 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); } | 586 const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_ inlineBuffer.buffer); } |
| 500 | 587 |
| 501 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; | 588 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; |
| 502 template<typename U, size_t inlineBuffer, typename V> | 589 template<typename U, size_t inlineBuffer, typename V> |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 543 | 630 |
| 544 template<typename Derived, typename Elements> | 631 template<typename Derived, typename Elements> |
| 545 class VectorDestructorBase<Derived, Elements, true, true> : public HeapVecto rWithInlineCapacityDestructorBase<Derived, VectorTraits<Elements>::needsDestruct ion> { }; | 632 class VectorDestructorBase<Derived, Elements, true, true> : public HeapVecto rWithInlineCapacityDestructorBase<Derived, VectorTraits<Elements>::needsDestruct ion> { }; |
| 546 | 633 |
| 547 template<typename T, size_t inlineCapacity = 0, typename Allocator = Default Allocator> | 634 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> { | 635 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); | 636 WTF_USE_ALLOCATOR(Vector, Allocator); |
| 550 private: | 637 private: |
| 551 typedef VectorBuffer<T, inlineCapacity, Allocator> Base; | 638 typedef VectorBuffer<T, inlineCapacity, Allocator> Base; |
| 552 typedef VectorTypeOperations<T> TypeOperations; | 639 typedef VectorTypeOperations<T> TypeOperations; |
| 640 typedef typename Base::Range Range; | |
| 553 | 641 |
| 554 public: | 642 public: |
| 555 typedef T ValueType; | 643 typedef T ValueType; |
| 556 | 644 |
| 557 typedef T* iterator; | 645 typedef T* iterator; |
| 558 typedef const T* const_iterator; | 646 typedef const T* const_iterator; |
| 559 typedef std::reverse_iterator<iterator> reverse_iterator; | 647 typedef std::reverse_iterator<iterator> reverse_iterator; |
| 560 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | 648 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; |
| 561 | 649 |
| 562 Vector() | 650 Vector() |
| 651 : m_size(0) | |
| 563 { | 652 { |
| 564 // Unused slots are initialized to zero so that the visitor and the | 653 // Unused slots are initialized to zero so that the visitor and the |
| 565 // finalizer can visit them safely. canInitializeWithMemset tells us | 654 // finalizer can visit them safely. canInitializeWithMemset tells us |
| 566 // that the class does not expect matching constructor and | 655 // that the class does not expect matching constructor and |
| 567 // destructor calls as long as the memory is zeroed. | 656 // destructor calls as long as the memory is zeroed. |
| 568 COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::n eedsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWit hFinalizersCalledOnClearedMemory); | 657 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); | 658 COMPILE_ASSERT(!WTF::IsPolymorphic<T>::value || !VectorTraits<T>::ca nInitializeWithMemset, CantInitializeWithMemsetIfThereIsAVtable); |
| 570 m_size = 0; | |
| 571 } | 659 } |
| 572 | 660 |
| 573 explicit Vector(size_t size) | 661 explicit Vector(size_t size) |
| 574 : Base(size) | 662 : Base(size) |
| 575 { | 663 { |
| 664 setSize(size); | |
| 576 // Unused slots are initialized to zero so that the visitor and the | 665 // Unused slots are initialized to zero so that the visitor and the |
| 577 // finalizer can visit them safely. canInitializeWithMemset tells us | 666 // finalizer can visit them safely. canInitializeWithMemset tells us |
| 578 // that the class does not expect matching constructor and | 667 // that the class does not expect matching constructor and |
| 579 // destructor calls as long as the memory is zeroed. | 668 // destructor calls as long as the memory is zeroed. |
| 580 COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::n eedsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWit hFinalizersCalledOnClearedMemory); | 669 COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::n eedsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWit hFinalizersCalledOnClearedMemory); |
| 581 m_size = size; | |
| 582 TypeOperations::initialize(begin(), end()); | 670 TypeOperations::initialize(begin(), end()); |
| 583 } | 671 } |
| 584 | 672 |
| 585 // Off-GC-heap vectors: Destructor should be called. | 673 // Off-GC-heap vectors: Destructor should be called. |
| 586 // On-GC-heap vectors: Destructor should be called for inline buffers | 674 // On-GC-heap vectors: Destructor should be called for inline buffers |
| 587 // (if any) but destructor shouldn't be called for vector backing since | 675 // (if any) but destructor shouldn't be called for vector backing since |
| 588 // it is managed by the traced GC heap. | 676 // it is managed by the traced GC heap. |
| 589 void finalize() | 677 void finalize() |
| 590 { | 678 { |
| 591 if (!inlineCapacity) { | 679 if (!inlineCapacity) { |
| 592 if (LIKELY(!Base::buffer())) | 680 if (LIKELY(!Base::buffer())) |
| 593 return; | 681 return; |
| 594 } | 682 } |
| 595 if (LIKELY(m_size) && !(Allocator::isGarbageCollected && this->hasOu tOfLineBuffer())) { | 683 if (LIKELY(size()) && !(Allocator::isGarbageCollected && this->hasOu tOfLineBuffer())) { |
| 596 TypeOperations::destruct(begin(), end()); | 684 TypeOperations::destruct(begin(), end()); |
| 597 m_size = 0; // Partial protection against use-after-free. | 685 setSize(0); // Partial protection against use-after-free. |
| 598 } | 686 } |
| 599 | 687 |
| 600 Base::destruct(); | 688 Base::destruct(); |
| 601 } | 689 } |
| 602 | 690 |
| 603 void finalizeGarbageCollectedObject() | 691 void finalizeGarbageCollectedObject() |
| 604 { | 692 { |
| 605 finalize(); | 693 finalize(); |
| 606 } | 694 } |
| 607 | 695 |
| 608 Vector(const Vector&); | 696 Vector(const Vector&); |
| 609 template<size_t otherCapacity> | 697 template<size_t otherInlineCapacity> |
| 610 explicit Vector(const Vector<T, otherCapacity, Allocator>&); | 698 explicit Vector(const Vector<T, otherInlineCapacity, Allocator>&); |
| 611 | 699 |
| 612 Vector& operator=(const Vector&); | 700 Vector& operator=(const Vector&); |
| 613 template<size_t otherCapacity> | 701 template<size_t otherInlineCapacity> |
| 614 Vector& operator=(const Vector<T, otherCapacity, Allocator>&); | 702 Vector& operator=(const Vector<T, otherInlineCapacity, Allocator>&); |
| 615 | 703 |
| 616 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) | 704 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) |
| 617 Vector(Vector&&); | 705 Vector(Vector&&); |
| 618 Vector& operator=(Vector&&); | 706 Vector& operator=(Vector&&); |
| 619 #endif | 707 #endif |
| 620 | 708 |
| 621 size_t size() const { return m_size; } | |
| 622 size_t capacity() const { return Base::capacity(); } | 709 size_t capacity() const { return Base::capacity(); } |
| 623 bool isEmpty() const { return !size(); } | 710 bool isEmpty() const { return !size(); } |
| 624 | 711 |
| 625 T& at(size_t i) | 712 T& at(size_t i) |
| 626 { | 713 { |
| 627 RELEASE_ASSERT(i < size()); | 714 RELEASE_ASSERT(i < size()); |
| 628 return Base::buffer()[i]; | 715 return Base::buffer()[i]; |
| 629 } | 716 } |
| 630 const T& at(size_t i) const | 717 const T& at(size_t i) const |
| 631 { | 718 { |
| 632 RELEASE_ASSERT(i < size()); | 719 RELEASE_ASSERT(i < size()); |
| 633 return Base::buffer()[i]; | 720 return Base::buffer()[i]; |
| 634 } | 721 } |
| 635 | 722 |
| 636 T& operator[](size_t i) { return at(i); } | 723 T& operator[](size_t i) { return at(i); } |
| 637 const T& operator[](size_t i) const { return at(i); } | 724 const T& operator[](size_t i) const { return at(i); } |
| 638 | 725 |
| 639 T* data() { return Base::buffer(); } | 726 T* data() { return Base::buffer(); } |
| 640 const T* data() const { return Base::buffer(); } | 727 const T* data() const { return Base::buffer(); } |
| 641 | 728 |
| 642 iterator begin() { return data(); } | 729 iterator begin() { return data(); } |
| 643 iterator end() { return begin() + m_size; } | 730 iterator end() { return begin() + size(); } |
| 644 const_iterator begin() const { return data(); } | 731 const_iterator begin() const { return data(); } |
| 645 const_iterator end() const { return begin() + m_size; } | 732 const_iterator end() const { return begin() + size(); } |
| 646 | 733 |
| 647 reverse_iterator rbegin() { return reverse_iterator(end()); } | 734 reverse_iterator rbegin() { return reverse_iterator(end()); } |
| 648 reverse_iterator rend() { return reverse_iterator(begin()); } | 735 reverse_iterator rend() { return reverse_iterator(begin()); } |
| 649 const_reverse_iterator rbegin() const { return const_reverse_iterator(en d()); } | 736 const_reverse_iterator rbegin() const { return const_reverse_iterator(en d()); } |
| 650 const_reverse_iterator rend() const { return const_reverse_iterator(begi n()); } | 737 const_reverse_iterator rend() const { return const_reverse_iterator(begi n()); } |
| 651 | 738 |
| 652 T& first() { return at(0); } | 739 T& first() { return at(0); } |
| 653 const T& first() const { return at(0); } | 740 const T& first() const { return at(0); } |
| 654 T& last() { return at(size() - 1); } | 741 T& last() { return at(size() - 1); } |
| 655 const T& last() const { return at(size() - 1); } | 742 const T& last() const { return at(size() - 1); } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 668 { | 755 { |
| 669 if (size() * 2 < capacity()) | 756 if (size() * 2 < capacity()) |
| 670 shrinkCapacity(size() + size() / 4 + 1); | 757 shrinkCapacity(size() + size() / 4 + 1); |
| 671 } | 758 } |
| 672 | 759 |
| 673 void clear() { shrinkCapacity(0); } | 760 void clear() { shrinkCapacity(0); } |
| 674 | 761 |
| 675 template<typename U> void append(const U*, size_t); | 762 template<typename U> void append(const U*, size_t); |
| 676 template<typename U> void append(const U&); | 763 template<typename U> void append(const U&); |
| 677 template<typename U> void uncheckedAppend(const U& val); | 764 template<typename U> void uncheckedAppend(const U& val); |
| 678 template<typename U, size_t otherCapacity, typename V> void appendVector (const Vector<U, otherCapacity, V>&); | 765 template<typename U, size_t otherInlineCapacity, typename V> void append Vector(const Vector<U, otherInlineCapacity, V>&); |
| 679 | 766 |
| 680 template<typename U> void insert(size_t position, const U*, size_t); | 767 template<typename U> void insert(size_t position, const U*, size_t); |
| 681 template<typename U> void insert(size_t position, const U&); | 768 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>&); | 769 template<typename U, size_t c, typename V> void insert(size_t position, const Vector<U, c, V>&); |
| 683 | 770 |
| 684 template<typename U> void prepend(const U*, size_t); | 771 template<typename U> void prepend(const U*, size_t); |
| 685 template<typename U> void prepend(const U&); | 772 template<typename U> void prepend(const U&); |
| 686 template<typename U, size_t c, typename V> void prepend(const Vector<U, c, V>&); | 773 template<typename U, size_t c, typename V> void prepend(const Vector<U, c, V>&); |
| 687 | 774 |
| 688 void remove(size_t position); | 775 void remove(size_t position); |
| 689 void remove(size_t position, size_t length); | 776 void remove(size_t position, size_t length); |
| 690 | 777 |
| 691 void removeLast() | 778 void removeLast() |
| 692 { | 779 { |
| 693 ASSERT(!isEmpty()); | 780 ASSERT(!isEmpty()); |
| 694 shrink(size() - 1); | 781 shrink(size() - 1); |
| 695 } | 782 } |
| 696 | 783 |
| 697 Vector(size_t size, const T& val) | 784 Vector(size_t size, const T& val) |
| 698 : Base(size) | 785 : Base(size) |
| 699 { | 786 { |
| 700 m_size = size; | 787 setSize(size); |
| 701 TypeOperations::uninitializedFill(begin(), end(), val); | 788 TypeOperations::uninitializedFill(begin(), end(), val); |
| 702 } | 789 } |
| 703 | 790 |
| 704 void fill(const T&, size_t); | 791 void fill(const T&, size_t); |
| 705 void fill(const T& val) { fill(val, size()); } | 792 void fill(const T& val) { fill(val, size()); } |
| 706 | 793 |
| 707 template<typename Iterator> void appendRange(Iterator start, Iterator en d); | 794 template<typename Iterator> void appendRange(Iterator start, Iterator en d); |
| 708 | 795 |
| 709 void swap(Vector& other) | 796 void swap(Vector& other); |
| 710 { | |
| 711 Base::swapVectorBuffer(other); | |
| 712 std::swap(m_size, other.m_size); | |
| 713 } | |
| 714 | 797 |
| 715 void reverse(); | 798 void reverse(); |
| 716 | 799 |
| 717 void trace(typename Allocator::Visitor*); | 800 void trace(typename Allocator::Visitor*); |
| 718 | 801 |
| 802 size_t size() const { return m_size; } | |
| 719 private: | 803 private: |
| 720 void expandCapacity(size_t newMinCapacity); | 804 void expandCapacity(size_t newMinCapacity); |
| 721 const T* expandCapacity(size_t newMinCapacity, const T*); | 805 const T* expandCapacity(size_t newMinCapacity, const T*); |
| 722 template<typename U> U* expandCapacity(size_t newMinCapacity, U*); | 806 template<typename U> U* expandCapacity(size_t newMinCapacity, U*); |
| 723 void shrinkCapacity(size_t newCapacity); | 807 void shrinkCapacity(size_t newCapacity); |
| 724 template<typename U> void appendSlowCase(const U&); | 808 template<typename U> void appendSlowCase(const U&); |
| 725 | 809 |
| 726 using Base::m_size; | 810 void setSize(unsigned size) |
| 811 { | |
| 812 m_size = size; | |
| 813 } | |
| 814 | |
| 815 unsigned m_size; | |
| 816 | |
| 727 using Base::buffer; | 817 using Base::buffer; |
| 728 using Base::capacity; | 818 using Base::capacity; |
| 729 using Base::swapVectorBuffer; | |
| 730 using Base::allocateBuffer; | 819 using Base::allocateBuffer; |
| 731 using Base::allocationSize; | 820 using Base::allocationSize; |
| 732 using Base::clearUnusedSlots; | 821 using Base::clearUnusedSlots; |
| 822 using Base::hasOutOfLineBuffer; | |
| 823 | |
| 824 friend class VectorBuffer<T, inlineCapacity, Allocator>; | |
| 733 }; | 825 }; |
| 734 | 826 |
| 735 template<typename T, size_t inlineCapacity, typename Allocator> | 827 template<typename T, size_t inlineCapacity, typename Allocator> |
| 828 void Vector<T, inlineCapacity, Allocator>::swap(Vector<T, inlineCapacity, Al locator>& other) | |
| 829 { | |
| 830 Base::swapVectorBuffer(other, Range(0, m_size), Range(0, other.m_size)); | |
| 831 std::swap(m_size, other.m_size); | |
| 832 } | |
| 833 | |
| 834 template<typename T, size_t inlineCapacity, typename Allocator> | |
| 736 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) | 835 Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other) |
| 737 : Base(other.capacity()) | 836 : Base(other.capacity()) |
| 738 { | 837 { |
| 739 m_size = other.size(); | 838 setSize(other.size()); |
| 740 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); | 839 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
| 741 } | 840 } |
| 742 | 841 |
| 743 template<typename T, size_t inlineCapacity, typename Allocator> | 842 template<typename T, size_t inlineCapacity, typename Allocator> |
| 744 template<size_t otherCapacity> | 843 template<size_t otherInlineCapacity> |
| 745 Vector<T, inlineCapacity, Allocator>::Vector(const Vector<T, otherCapacity, Allocator>& other) | 844 Vector<T, inlineCapacity, Allocator>::Vector(const Vector<T, otherInlineCapa city, Allocator>& other) |
| 746 : Base(other.capacity()) | 845 : Base(other.capacity()) |
| 747 { | 846 { |
| 748 m_size = other.size(); | 847 setSize(other.size()); |
| 749 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); | 848 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
| 750 } | 849 } |
| 751 | 850 |
| 752 template<typename T, size_t inlineCapacity, typename Allocator> | 851 template<typename T, size_t inlineCapacity, typename Allocator> |
| 753 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, inlineCapacity, Allocator>& other) | 852 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, inlineCapacity, Allocator>& other) |
| 754 { | 853 { |
| 755 if (UNLIKELY(&other == this)) | 854 if (UNLIKELY(&other == this)) |
| 756 return *this; | 855 return *this; |
| 757 | 856 |
| 758 if (size() > other.size()) | 857 if (size() > other.size()) |
| 759 shrink(other.size()); | 858 shrink(other.size()); |
| 760 else if (other.size() > capacity()) { | 859 else if (other.size() > capacity()) { |
| 761 clear(); | 860 clear(); |
| 762 reserveCapacity(other.size()); | 861 reserveCapacity(other.size()); |
| 763 ASSERT(begin()); | 862 ASSERT(begin()); |
| 764 } | 863 } |
| 765 | 864 |
| 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 | 865 // 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 | 866 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL |
| 768 if (!begin()) | 867 if (!begin()) |
| 769 return *this; | 868 return *this; |
| 770 #endif | 869 #endif |
| 771 | 870 |
| 772 std::copy(other.begin(), other.begin() + size(), begin()); | 871 std::copy(other.begin(), other.begin() + size(), begin()); |
| 773 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); | 872 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); |
| 774 m_size = other.size(); | 873 setSize(other.size()); |
| 775 | 874 |
| 776 return *this; | 875 return *this; |
| 777 } | 876 } |
| 778 | 877 |
| 779 inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; } | 878 inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; } |
| 780 | 879 |
| 781 template<typename T, size_t inlineCapacity, typename Allocator> | 880 template<typename T, size_t inlineCapacity, typename Allocator> |
| 782 template<size_t otherCapacity> | 881 template<size_t otherInlineCapacity> |
| 783 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, otherCapacity, Allocator>& other) | 882 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(const Vector<T, otherInlineCapacity, Allocator>& other) |
| 784 { | 883 { |
| 785 // If the inline capacities match, we should call the more specific | 884 // If the inline capacities match, we should call the more specific |
| 786 // template. If the inline capacities don't match, the two objects | 885 // template. If the inline capacities don't match, the two objects |
| 787 // shouldn't be allocated the same address. | 886 // shouldn't be allocated the same address. |
| 788 ASSERT(!typelessPointersAreEqual(&other, this)); | 887 ASSERT(!typelessPointersAreEqual(&other, this)); |
| 789 | 888 |
| 790 if (size() > other.size()) | 889 if (size() > other.size()) |
| 791 shrink(other.size()); | 890 shrink(other.size()); |
| 792 else if (other.size() > capacity()) { | 891 else if (other.size() > capacity()) { |
| 793 clear(); | 892 clear(); |
| 794 reserveCapacity(other.size()); | 893 reserveCapacity(other.size()); |
| 795 ASSERT(begin()); | 894 ASSERT(begin()); |
| 796 } | 895 } |
| 797 | 896 |
| 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 | 897 // 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 | 898 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL |
| 800 if (!begin()) | 899 if (!begin()) |
| 801 return *this; | 900 return *this; |
| 802 #endif | 901 #endif |
| 803 | 902 |
| 804 std::copy(other.begin(), other.begin() + size(), begin()); | 903 std::copy(other.begin(), other.begin() + size(), begin()); |
| 805 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); | 904 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd()); |
| 806 m_size = other.size(); | 905 setSize(other.size()); |
| 807 | 906 |
| 808 return *this; | 907 return *this; |
| 809 } | 908 } |
| 810 | 909 |
| 811 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) | 910 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) |
| 812 template<typename T, size_t inlineCapacity, typename Allocator> | 911 template<typename T, size_t inlineCapacity, typename Allocator> |
| 813 Vector<T, inlineCapacity, Allocator>::Vector(Vector<T, inlineCapacity, Alloc ator>&& other) | 912 Vector<T, inlineCapacity, Allocator>::Vector(Vector<T, inlineCapacity, Alloc ator>&& other) |
| 814 { | 913 { |
| 815 m_size = 0; | 914 setSize(0); |
| 816 // It's a little weird to implement a move constructor using swap but th is way we | 915 // 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. | 916 // don't have to add a move constructor to VectorBuffer. |
| 818 swap(other); | 917 swap(other); |
| 819 } | 918 } |
| 820 | 919 |
| 821 template<typename T, size_t inlineCapacity, typename Allocator> | 920 template<typename T, size_t inlineCapacity, typename Allocator> |
| 822 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(Vector<T, inlineCapacity, Allocator>&& other) | 921 Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>:: operator=(Vector<T, inlineCapacity, Allocator>&& other) |
| 823 { | 922 { |
| 824 swap(other); | 923 swap(other); |
| 825 return *this; | 924 return *this; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 866 if (size() > newSize) | 965 if (size() > newSize) |
| 867 shrink(newSize); | 966 shrink(newSize); |
| 868 else if (newSize > capacity()) { | 967 else if (newSize > capacity()) { |
| 869 clear(); | 968 clear(); |
| 870 reserveCapacity(newSize); | 969 reserveCapacity(newSize); |
| 871 ASSERT(begin()); | 970 ASSERT(begin()); |
| 872 } | 971 } |
| 873 | 972 |
| 874 std::fill(begin(), end(), val); | 973 std::fill(begin(), end(), val); |
| 875 TypeOperations::uninitializedFill(end(), begin() + newSize, val); | 974 TypeOperations::uninitializedFill(end(), begin() + newSize, val); |
| 876 m_size = newSize; | 975 setSize(newSize); |
| 877 } | 976 } |
| 878 | 977 |
| 879 template<typename T, size_t inlineCapacity, typename Allocator> | 978 template<typename T, size_t inlineCapacity, typename Allocator> |
| 880 template<typename Iterator> | 979 template<typename Iterator> |
| 881 void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start, Itera tor end) | 980 void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start, Itera tor end) |
| 882 { | 981 { |
| 883 for (Iterator it = start; it != end; ++it) | 982 for (Iterator it = start; it != end; ++it) |
| 884 append(*it); | 983 append(*it); |
| 885 } | 984 } |
| 886 | 985 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 919 } | 1018 } |
| 920 | 1019 |
| 921 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1020 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) | 1021 inline U* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMin Capacity, U* ptr) |
| 923 { | 1022 { |
| 924 expandCapacity(newMinCapacity); | 1023 expandCapacity(newMinCapacity); |
| 925 return ptr; | 1024 return ptr; |
| 926 } | 1025 } |
| 927 | 1026 |
| 928 template<typename T, size_t inlineCapacity, typename Allocator> | 1027 template<typename T, size_t inlineCapacity, typename Allocator> |
| 929 inline void Vector<T, inlineCapacity, Allocator>::resize(size_t size) | 1028 inline void Vector<T, inlineCapacity, Allocator>::resize(size_t sizeArg) |
| 930 { | 1029 { |
| 931 if (size <= m_size) | 1030 if (sizeArg <= size()) |
| 932 TypeOperations::destruct(begin() + size, end()); | 1031 TypeOperations::destruct(begin() + sizeArg, end()); |
| 933 else { | 1032 else { |
| 934 if (size > capacity()) | 1033 if (sizeArg > capacity()) |
| 935 expandCapacity(size); | 1034 expandCapacity(sizeArg); |
| 936 TypeOperations::initialize(end(), begin() + size); | 1035 TypeOperations::initialize(end(), begin() + sizeArg); |
| 937 } | 1036 } |
| 938 | 1037 |
| 939 m_size = size; | 1038 setSize(sizeArg); |
| 940 } | 1039 } |
| 941 | 1040 |
| 942 template<typename T, size_t inlineCapacity, typename Allocator> | 1041 template<typename T, size_t inlineCapacity, typename Allocator> |
| 943 void Vector<T, inlineCapacity, Allocator>::shrink(size_t size) | 1042 void Vector<T, inlineCapacity, Allocator>::shrink(size_t sizeArg) |
| 944 { | 1043 { |
| 945 ASSERT(size <= m_size); | 1044 ASSERT(sizeArg <= size()); |
| 946 TypeOperations::destruct(begin() + size, end()); | 1045 TypeOperations::destruct(begin() + sizeArg, end()); |
| 947 clearUnusedSlots(begin() + size, end()); | 1046 clearUnusedSlots(begin() + sizeArg, end()); |
| 948 m_size = size; | 1047 setSize(sizeArg); |
| 949 } | 1048 } |
| 950 | 1049 |
| 951 template<typename T, size_t inlineCapacity, typename Allocator> | 1050 template<typename T, size_t inlineCapacity, typename Allocator> |
| 952 void Vector<T, inlineCapacity, Allocator>::grow(size_t size) | 1051 void Vector<T, inlineCapacity, Allocator>::grow(size_t sizeArg) |
| 953 { | 1052 { |
| 954 ASSERT(size >= m_size); | 1053 ASSERT(sizeArg >= size()); |
| 955 if (size > capacity()) | 1054 if (sizeArg > capacity()) |
| 956 expandCapacity(size); | 1055 expandCapacity(sizeArg); |
| 957 TypeOperations::initialize(end(), begin() + size); | 1056 TypeOperations::initialize(end(), begin() + sizeArg); |
| 958 m_size = size; | 1057 setSize(sizeArg); |
| 959 } | 1058 } |
| 960 | 1059 |
| 961 template<typename T, size_t inlineCapacity, typename Allocator> | 1060 template<typename T, size_t inlineCapacity, typename Allocator> |
| 962 void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacit y) | 1061 void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacit y) |
| 963 { | 1062 { |
| 964 if (UNLIKELY(newCapacity <= capacity())) | 1063 if (UNLIKELY(newCapacity <= capacity())) |
| 965 return; | 1064 return; |
| 966 T* oldBuffer = begin(); | 1065 T* oldBuffer = begin(); |
| 967 T* oldEnd = end(); | 1066 T* oldEnd = end(); |
| 968 Base::allocateBuffer(newCapacity); | 1067 Base::allocateBuffer(newCapacity); |
| 969 TypeOperations::move(oldBuffer, oldEnd, begin()); | 1068 TypeOperations::move(oldBuffer, oldEnd, begin()); |
| 970 Base::deallocateBuffer(oldBuffer); | 1069 Base::deallocateBuffer(oldBuffer); |
| 971 } | 1070 } |
| 972 | 1071 |
| 973 template<typename T, size_t inlineCapacity, typename Allocator> | 1072 template<typename T, size_t inlineCapacity, typename Allocator> |
| 974 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(siz e_t initialCapacity) | 1073 inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(siz e_t initialCapacity) |
| 975 { | 1074 { |
| 976 ASSERT(!m_size); | 1075 ASSERT(!size()); |
| 977 ASSERT(capacity() == inlineCapacity); | 1076 ASSERT(capacity() == inlineCapacity); |
| 978 if (initialCapacity > inlineCapacity) | 1077 if (initialCapacity > inlineCapacity) |
| 979 Base::allocateBuffer(initialCapacity); | 1078 Base::allocateBuffer(initialCapacity); |
| 980 } | 1079 } |
| 981 | 1080 |
| 982 template<typename T, size_t inlineCapacity, typename Allocator> | 1081 template<typename T, size_t inlineCapacity, typename Allocator> |
| 983 void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity ) | 1082 void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity ) |
| 984 { | 1083 { |
| 985 if (newCapacity >= capacity()) | 1084 if (newCapacity >= capacity()) |
| 986 return; | 1085 return; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1005 Base::deallocateBuffer(oldBuffer); | 1104 Base::deallocateBuffer(oldBuffer); |
| 1006 } | 1105 } |
| 1007 | 1106 |
| 1008 // Templatizing these is better than just letting the conversion happen impl icitly, | 1107 // 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 | 1108 // because for instance it allows a PassRefPtr to be appended to a RefPtr ve ctor |
| 1010 // without refcount thrash. | 1109 // without refcount thrash. |
| 1011 | 1110 |
| 1012 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1111 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) | 1112 void Vector<T, inlineCapacity, Allocator>::append(const U* data, size_t data Size) |
| 1014 { | 1113 { |
| 1015 size_t newSize = m_size + dataSize; | 1114 size_t newSize = size() + dataSize; |
| 1016 if (newSize > capacity()) { | 1115 if (newSize > capacity()) { |
| 1017 data = expandCapacity(newSize, data); | 1116 data = expandCapacity(newSize, data); |
| 1018 ASSERT(begin()); | 1117 ASSERT(begin()); |
| 1019 } | 1118 } |
| 1020 RELEASE_ASSERT(newSize >= m_size); | 1119 RELEASE_ASSERT(newSize >= size()); |
| 1021 T* dest = end(); | 1120 T* dest = end(); |
| 1022 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], dest); | 1121 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], dest); |
| 1023 m_size = newSize; | 1122 setSize(newSize); |
| 1024 } | 1123 } |
| 1025 | 1124 |
| 1026 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1125 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
| 1027 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val ) | 1126 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val ) |
| 1028 { | 1127 { |
| 1029 if (LIKELY(size() != capacity())) { | 1128 if (LIKELY(size() != capacity())) { |
| 1030 new (NotNull, end()) T(val); | 1129 new (NotNull, end()) T(val); |
| 1031 ++m_size; | 1130 setSize(size() + 1); |
| 1032 return; | 1131 return; |
| 1033 } | 1132 } |
| 1034 | 1133 |
| 1035 appendSlowCase(val); | 1134 appendSlowCase(val); |
| 1036 } | 1135 } |
| 1037 | 1136 |
| 1038 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1137 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> |
| 1039 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U& val) | 1138 NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U& val) |
| 1040 { | 1139 { |
| 1041 ASSERT(size() == capacity()); | 1140 ASSERT(size() == capacity()); |
| 1042 | 1141 |
| 1043 const U* ptr = &val; | 1142 const U* ptr = &val; |
| 1044 ptr = expandCapacity(size() + 1, ptr); | 1143 ptr = expandCapacity(size() + 1, ptr); |
| 1045 ASSERT(begin()); | 1144 ASSERT(begin()); |
| 1046 | 1145 |
| 1047 new (NotNull, end()) T(*ptr); | 1146 new (NotNull, end()) T(*ptr); |
| 1048 ++m_size; | 1147 setSize(size() + 1); |
| 1049 } | 1148 } |
| 1050 | 1149 |
| 1051 // This version of append saves a branch in the case where you know that the | 1150 // 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. | 1151 // vector's capacity is large enough for the append to succeed. |
| 1053 | 1152 |
| 1054 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1153 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) | 1154 ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(con st U& val) |
| 1056 { | 1155 { |
| 1057 ASSERT(size() < capacity()); | 1156 ASSERT(size() < capacity()); |
| 1058 const U* ptr = &val; | 1157 const U* ptr = &val; |
| 1059 new (NotNull, end()) T(*ptr); | 1158 new (NotNull, end()) T(*ptr); |
| 1060 ++m_size; | 1159 setSize(size() + 1); |
| 1061 } | 1160 } |
| 1062 | 1161 |
| 1063 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U, size_t otherCapacity, typename OtherAllocator> | 1162 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) | 1163 inline void Vector<T, inlineCapacity, Allocator>::appendVector(const Vector< U, otherInlineCapacity, OtherAllocator>& val) |
| 1065 { | 1164 { |
| 1066 append(val.begin(), val.size()); | 1165 append(val.begin(), val.size()); |
| 1067 } | 1166 } |
| 1068 | 1167 |
| 1069 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1168 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) | 1169 void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U* data, size_t dataSize) |
| 1071 { | 1170 { |
| 1072 RELEASE_ASSERT(position <= size()); | 1171 RELEASE_ASSERT(position <= size()); |
| 1073 size_t newSize = m_size + dataSize; | 1172 size_t newSize = size() + dataSize; |
| 1074 if (newSize > capacity()) { | 1173 if (newSize > capacity()) { |
| 1075 data = expandCapacity(newSize, data); | 1174 data = expandCapacity(newSize, data); |
| 1076 ASSERT(begin()); | 1175 ASSERT(begin()); |
| 1077 } | 1176 } |
| 1078 RELEASE_ASSERT(newSize >= m_size); | 1177 RELEASE_ASSERT(newSize >= size()); |
| 1079 T* spot = begin() + position; | 1178 T* spot = begin() + position; |
| 1080 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); | 1179 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); |
| 1081 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], spot); | 1180 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(d ata, &data[dataSize], spot); |
| 1082 m_size = newSize; | 1181 setSize(newSize); |
| 1083 } | 1182 } |
| 1084 | 1183 |
| 1085 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1184 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) | 1185 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, co nst U& val) |
| 1087 { | 1186 { |
| 1088 RELEASE_ASSERT(position <= size()); | 1187 RELEASE_ASSERT(position <= size()); |
| 1089 const U* data = &val; | 1188 const U* data = &val; |
| 1090 if (size() == capacity()) { | 1189 if (size() == capacity()) { |
| 1091 data = expandCapacity(size() + 1, data); | 1190 data = expandCapacity(size() + 1, data); |
| 1092 ASSERT(begin()); | 1191 ASSERT(begin()); |
| 1093 } | 1192 } |
| 1094 T* spot = begin() + position; | 1193 T* spot = begin() + position; |
| 1095 TypeOperations::moveOverlapping(spot, end(), spot + 1); | 1194 TypeOperations::moveOverlapping(spot, end(), spot + 1); |
| 1096 new (NotNull, spot) T(*data); | 1195 new (NotNull, spot) T(*data); |
| 1097 ++m_size; | 1196 setSize(size() + 1); |
| 1098 } | 1197 } |
| 1099 | 1198 |
| 1100 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U, size_t c, typename OtherAllocator> | 1199 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) | 1200 inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, co nst Vector<U, c, OtherAllocator>& val) |
| 1102 { | 1201 { |
| 1103 insert(position, val.begin(), val.size()); | 1202 insert(position, val.begin(), val.size()); |
| 1104 } | 1203 } |
| 1105 | 1204 |
| 1106 template<typename T, size_t inlineCapacity, typename Allocator> template<typ ename U> | 1205 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) | 1206 void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, size_t dat aSize) |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1122 } | 1221 } |
| 1123 | 1222 |
| 1124 template<typename T, size_t inlineCapacity, typename Allocator> | 1223 template<typename T, size_t inlineCapacity, typename Allocator> |
| 1125 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) | 1224 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position) |
| 1126 { | 1225 { |
| 1127 RELEASE_ASSERT(position < size()); | 1226 RELEASE_ASSERT(position < size()); |
| 1128 T* spot = begin() + position; | 1227 T* spot = begin() + position; |
| 1129 spot->~T(); | 1228 spot->~T(); |
| 1130 TypeOperations::moveOverlapping(spot + 1, end(), spot); | 1229 TypeOperations::moveOverlapping(spot + 1, end(), spot); |
| 1131 clearUnusedSlots(end() - 1, end()); | 1230 clearUnusedSlots(end() - 1, end()); |
| 1132 --m_size; | 1231 setSize(size() - 1); |
| 1133 } | 1232 } |
| 1134 | 1233 |
| 1135 template<typename T, size_t inlineCapacity, typename Allocator> | 1234 template<typename T, size_t inlineCapacity, typename Allocator> |
| 1136 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position, si ze_t length) | 1235 inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position, si ze_t length) |
| 1137 { | 1236 { |
| 1138 ASSERT_WITH_SECURITY_IMPLICATION(position <= size()); | 1237 ASSERT_WITH_SECURITY_IMPLICATION(position <= size()); |
| 1139 RELEASE_ASSERT(position + length <= size()); | 1238 RELEASE_ASSERT(position + length <= size()); |
| 1140 T* beginSpot = begin() + position; | 1239 T* beginSpot = begin() + position; |
| 1141 T* endSpot = beginSpot + length; | 1240 T* endSpot = beginSpot + length; |
| 1142 TypeOperations::destruct(beginSpot, endSpot); | 1241 TypeOperations::destruct(beginSpot, endSpot); |
| 1143 TypeOperations::moveOverlapping(endSpot, end(), beginSpot); | 1242 TypeOperations::moveOverlapping(endSpot, end(), beginSpot); |
| 1144 clearUnusedSlots(end() - length, end()); | 1243 clearUnusedSlots(end() - length, end()); |
| 1145 m_size -= length; | 1244 setSize(size() - length); |
| 1146 } | 1245 } |
| 1147 | 1246 |
| 1148 template<typename T, size_t inlineCapacity, typename Allocator> | 1247 template<typename T, size_t inlineCapacity, typename Allocator> |
| 1149 inline void Vector<T, inlineCapacity, Allocator>::reverse() | 1248 inline void Vector<T, inlineCapacity, Allocator>::reverse() |
| 1150 { | 1249 { |
| 1151 for (size_t i = 0; i < m_size / 2; ++i) | 1250 for (size_t i = 0; i < size() / 2; ++i) |
| 1152 std::swap(at(i), at(m_size - 1 - i)); | 1251 std::swap(at(i), at(size() - 1 - i)); |
| 1153 } | 1252 } |
| 1154 | 1253 |
| 1155 template<typename T, size_t inlineCapacity, typename Allocator> | 1254 template<typename T, size_t inlineCapacity, typename Allocator> |
| 1156 void deleteAllValues(const Vector<T, inlineCapacity, Allocator>& collection) | 1255 void deleteAllValues(const Vector<T, inlineCapacity, Allocator>& collection) |
| 1157 { | 1256 { |
| 1158 typedef typename Vector<T, inlineCapacity, Allocator>::const_iterator it erator; | 1257 typedef typename Vector<T, inlineCapacity, Allocator>::const_iterator it erator; |
| 1159 iterator end = collection.end(); | 1258 iterator end = collection.end(); |
| 1160 for (iterator it = collection.begin(); it != end; ++it) | 1259 for (iterator it = collection.begin(); it != end; ++it) |
| 1161 delete *it; | 1260 delete *it; |
| 1162 } | 1261 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1203 struct NeedsTracing<Vector<T, N> > { | 1302 struct NeedsTracing<Vector<T, N> > { |
| 1204 static const bool value = false; | 1303 static const bool value = false; |
| 1205 }; | 1304 }; |
| 1206 #endif | 1305 #endif |
| 1207 | 1306 |
| 1208 } // namespace WTF | 1307 } // namespace WTF |
| 1209 | 1308 |
| 1210 using WTF::Vector; | 1309 using WTF::Vector; |
| 1211 | 1310 |
| 1212 #endif // WTF_Vector_h | 1311 #endif // WTF_Vector_h |
| OLD | NEW |