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