| 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 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 , m_capacity(0) | 306 , m_capacity(0) |
| 307 { | 307 { |
| 308 } | 308 } |
| 309 | 309 |
| 310 VectorBufferBase(T* buffer, size_t capacity) | 310 VectorBufferBase(T* buffer, size_t capacity) |
| 311 : m_buffer(buffer) | 311 : m_buffer(buffer) |
| 312 , m_capacity(capacity) | 312 , m_capacity(capacity) |
| 313 { | 313 { |
| 314 } | 314 } |
| 315 | 315 |
| 316 ~VectorBufferBase() | |
| 317 { | |
| 318 } | |
| 319 | |
| 320 T* m_buffer; | 316 T* m_buffer; |
| 321 unsigned m_capacity; | 317 unsigned m_capacity; |
| 322 unsigned m_size; | 318 unsigned m_size; |
| 323 }; | 319 }; |
| 324 | 320 |
| 325 template<typename T, size_t inlineCapacity, typename Allocator = DefaultAllo
cator> | 321 template<typename T, size_t inlineCapacity, typename Allocator = DefaultAllo
cator> |
| 326 class VectorBuffer; | 322 class VectorBuffer; |
| 327 | 323 |
| 328 template<typename T, typename Allocator> | 324 template<typename T, typename Allocator> |
| 329 class VectorBuffer<T, 0, Allocator> : private VectorBufferBase<T, Allocator>
{ | 325 class VectorBuffer<T, 0, Allocator> : private VectorBufferBase<T, Allocator>
{ |
| 330 private: | 326 private: |
| 331 typedef VectorBufferBase<T, Allocator> Base; | 327 typedef VectorBufferBase<T, Allocator> Base; |
| 332 public: | 328 public: |
| 333 VectorBuffer() | 329 VectorBuffer() |
| 334 { | 330 { |
| 335 } | 331 } |
| 336 | 332 |
| 337 VectorBuffer(size_t capacity) | 333 VectorBuffer(size_t capacity) |
| 338 { | 334 { |
| 339 // Calling malloc(0) might take a lock and may actually do an | 335 // Calling malloc(0) might take a lock and may actually do an |
| 340 // allocation on some systems. | 336 // allocation on some systems. |
| 341 if (capacity) | 337 if (capacity) |
| 342 allocateBuffer(capacity); | 338 allocateBuffer(capacity); |
| 343 } | 339 } |
| 344 | 340 |
| 345 ~VectorBuffer() | |
| 346 { | |
| 347 } | |
| 348 | |
| 349 void destruct() | 341 void destruct() |
| 350 { | 342 { |
| 351 deallocateBuffer(m_buffer); | 343 deallocateBuffer(m_buffer); |
| 352 m_buffer = 0; | 344 m_buffer = 0; |
| 353 } | 345 } |
| 354 | 346 |
| 355 void deallocateBuffer(T* bufferToDeallocate) | 347 void deallocateBuffer(T* bufferToDeallocate) |
| 356 { | 348 { |
| 357 Allocator::backingFree(bufferToDeallocate); | 349 Allocator::backingFree(bufferToDeallocate); |
| 358 } | 350 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 { | 392 { |
| 401 } | 393 } |
| 402 | 394 |
| 403 VectorBuffer(size_t capacity) | 395 VectorBuffer(size_t capacity) |
| 404 : Base(inlineBuffer(), inlineCapacity) | 396 : Base(inlineBuffer(), inlineCapacity) |
| 405 { | 397 { |
| 406 if (capacity > inlineCapacity) | 398 if (capacity > inlineCapacity) |
| 407 Base::allocateBuffer(capacity); | 399 Base::allocateBuffer(capacity); |
| 408 } | 400 } |
| 409 | 401 |
| 410 ~VectorBuffer() | |
| 411 { | |
| 412 } | |
| 413 | |
| 414 void destruct() | 402 void destruct() |
| 415 { | 403 { |
| 416 deallocateBuffer(m_buffer); | 404 deallocateBuffer(m_buffer); |
| 417 m_buffer = 0; | 405 m_buffer = 0; |
| 418 } | 406 } |
| 419 | 407 |
| 420 NEVER_INLINE void reallyDeallocateBuffer(T* bufferToDeallocate) | 408 NEVER_INLINE void reallyDeallocateBuffer(T* bufferToDeallocate) |
| 421 { | 409 { |
| 422 Allocator::backingFree(bufferToDeallocate); | 410 Allocator::backingFree(bufferToDeallocate); |
| 423 } | 411 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 using Base::m_buffer; | 474 using Base::m_buffer; |
| 487 using Base::m_capacity; | 475 using Base::m_capacity; |
| 488 | 476 |
| 489 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); | 477 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); |
| 490 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffe
r); } | 478 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffe
r); } |
| 491 const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_
inlineBuffer.buffer); } | 479 const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_
inlineBuffer.buffer); } |
| 492 | 480 |
| 493 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; | 481 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; |
| 494 }; | 482 }; |
| 495 | 483 |
| 484 template<typename T, size_t inlineCapacity, typename Allocator> |
| 485 class Vector; |
| 486 |
| 487 // VectorDestructorBase defines the destructor of a vector. This base is use
d in order to |
| 488 // completely avoid creating a destructor for a vector that does not need to
be destructed. |
| 489 // By doing so, the clang compiler will have correct information about wheth
er or not a |
| 490 // vector has a trivial destructor and we use that in a compiler plugin to e
nsure the |
| 491 // correctness of non-finalized garbage-collected classes and the use of Vec
torTraits::needsDestruction. |
| 492 |
| 493 // All non-GC managed vectors needs a destructor. This destructor will simpl
y call finalize on the actual vector type. |
| 494 template<typename Derived, typename Elements, bool hasInlineCapacity, bool i
sGarbageCollected> |
| 495 class VectorDestructorBase { |
| 496 public: |
| 497 ~VectorDestructorBase() { static_cast<Derived*>(this)->finalize(); } |
| 498 }; |
| 499 |
| 500 // Heap-allocated vectors with no inlineCapacity never need a destructor. |
| 501 template<typename Derived, typename Elements> |
| 502 class VectorDestructorBase<Derived, Elements, true, true> { }; |
| 503 |
| 504 // Heap-allocator vectors with inlineCapacity need a destructor if the inlin
e elements do. |
| 505 // The use of VectorTraits<Elements>::needsDestruction is delayed until we k
now that |
| 506 // inlineCapacity is non-zero to allow classes that recursively refer to the
mselves in vector |
| 507 // members. If inlineCapacity is non-zero doing so would have undefined mean
ing, so in this |
| 508 // case we can use HeapVectorWithInlineCapacityDestructorBase to define a de
structor |
| 509 // depending on the value of VectorTraits<Elements>::needsDestruction. |
| 510 template<typename Derived, bool elementsNeedsDestruction> |
| 511 class HeapVectorWithInlineCapacityDestructorBase; |
| 512 |
| 513 template<typename Derived> |
| 514 class HeapVectorWithInlineCapacityDestructorBase<Derived, true> { |
| 515 public: |
| 516 ~HeapVectorWithInlineCapacityDestructorBase() { static_cast<Derived*>(th
is)->finalize(); } |
| 517 }; |
| 518 |
| 519 template<typename Derived> |
| 520 class HeapVectorWithInlineCapacityDestructorBase<Derived, false> { }; |
| 521 |
| 522 template<typename Derived, typename Elements> |
| 523 class VectorDestructorBase<Derived, Elements, false, true> : public HeapVect
orWithInlineCapacityDestructorBase<Derived, VectorTraits<Elements>::needsDestruc
tion> { }; |
| 524 |
| 496 template<typename T, size_t inlineCapacity = 0, typename Allocator = Default
Allocator> | 525 template<typename T, size_t inlineCapacity = 0, typename Allocator = Default
Allocator> |
| 497 class Vector : private VectorBuffer<T, inlineCapacity, Allocator> { | 526 class Vector : private VectorBuffer<T, inlineCapacity, Allocator>, public Ve
ctorDestructorBase<Vector<T, inlineCapacity, Allocator>, T, (inlineCapacity > 0)
, Allocator::isGarbageCollected> { |
| 498 private: | 527 private: |
| 499 typedef VectorBuffer<T, inlineCapacity, Allocator> Base; | 528 typedef VectorBuffer<T, inlineCapacity, Allocator> Base; |
| 500 typedef VectorTypeOperations<T> TypeOperations; | 529 typedef VectorTypeOperations<T> TypeOperations; |
| 501 | 530 |
| 502 public: | 531 public: |
| 503 typedef T ValueType; | 532 typedef T ValueType; |
| 504 | 533 |
| 505 typedef T* iterator; | 534 typedef T* iterator; |
| 506 typedef const T* const_iterator; | 535 typedef const T* const_iterator; |
| 507 typedef std::reverse_iterator<iterator> reverse_iterator; | 536 typedef std::reverse_iterator<iterator> reverse_iterator; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 529 : Base(size) | 558 : Base(size) |
| 530 { | 559 { |
| 531 m_size = size; | 560 m_size = size; |
| 532 TypeOperations::initialize(begin(), end()); | 561 TypeOperations::initialize(begin(), end()); |
| 533 } | 562 } |
| 534 | 563 |
| 535 // Off-GC-heap vectors: Destructor should be called. | 564 // Off-GC-heap vectors: Destructor should be called. |
| 536 // On-GC-heap vectors: Destructor should be called for inline buffers | 565 // On-GC-heap vectors: Destructor should be called for inline buffers |
| 537 // (if any) but destructor shouldn't be called for vector backing since | 566 // (if any) but destructor shouldn't be called for vector backing since |
| 538 // it is managed by the traced GC heap. | 567 // it is managed by the traced GC heap. |
| 539 ~Vector() | 568 void finalize() |
| 540 { | 569 { |
| 541 if (!inlineCapacity) { | 570 if (!inlineCapacity) { |
| 542 if (LIKELY(!Base::buffer())) | 571 if (LIKELY(!Base::buffer())) |
| 543 return; | 572 return; |
| 544 } | 573 } |
| 545 if (LIKELY(m_size) && !(Allocator::isGarbageCollected && this->hasOu
tOfLineBuffer())) { | 574 if (LIKELY(m_size) && !(Allocator::isGarbageCollected && this->hasOu
tOfLineBuffer())) { |
| 546 TypeOperations::destruct(begin(), end()); | 575 TypeOperations::destruct(begin(), end()); |
| 547 m_size = 0; // Partial protection against use-after-free. | 576 m_size = 0; // Partial protection against use-after-free. |
| 548 } | 577 } |
| 549 | 578 |
| 550 Base::destruct(); | 579 Base::destruct(); |
| 551 } | 580 } |
| 552 | 581 |
| 553 void finalize() | |
| 554 { | |
| 555 this->~Vector(); | |
| 556 } | |
| 557 | |
| 558 void clearUnusedSlots(T* from, T* to) | 582 void clearUnusedSlots(T* from, T* to) |
| 559 { | 583 { |
| 560 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTrai
ts<T>::needsDestruction || ShouldBeTraced<VectorTraits<T> >::value || VectorTrai
ts<T>::isWeak), T>::clear(from, to); | 584 VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTrai
ts<T>::needsDestruction || ShouldBeTraced<VectorTraits<T> >::value || VectorTrai
ts<T>::isWeak), T>::clear(from, to); |
| 561 } | 585 } |
| 562 | 586 |
| 563 Vector(const Vector&); | 587 Vector(const Vector&); |
| 564 template<size_t otherCapacity> | 588 template<size_t otherCapacity> |
| 565 explicit Vector(const Vector<T, otherCapacity, Allocator>&); | 589 explicit Vector(const Vector<T, otherCapacity, Allocator>&); |
| 566 | 590 |
| 567 Vector& operator=(const Vector&); | 591 Vector& operator=(const Vector&); |
| (...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1145 } | 1169 } |
| 1146 if (this->hasOutOfLineBuffer()) | 1170 if (this->hasOutOfLineBuffer()) |
| 1147 Allocator::markNoTracing(visitor, buffer()); | 1171 Allocator::markNoTracing(visitor, buffer()); |
| 1148 } | 1172 } |
| 1149 | 1173 |
| 1150 } // namespace WTF | 1174 } // namespace WTF |
| 1151 | 1175 |
| 1152 using WTF::Vector; | 1176 using WTF::Vector; |
| 1153 | 1177 |
| 1154 #endif // WTF_Vector_h | 1178 #endif // WTF_Vector_h |
| OLD | NEW |