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, false, 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, true, true> : public HeapVecto
rWithInlineCapacityDestructorBase<Derived, VectorTraits<Elements>::needsDestruct
ion> { }; |
| 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 |