OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef HeapAllocator_h | 5 #ifndef HeapAllocator_h |
6 #define HeapAllocator_h | 6 #define HeapAllocator_h |
7 | 7 |
8 #include "platform/heap/Heap.h" | 8 #include "platform/heap/Heap.h" |
9 #include "platform/heap/TraceTraits.h" | 9 #include "platform/heap/TraceTraits.h" |
| 10 #include "wtf/Allocator.h" |
10 #include "wtf/Assertions.h" | 11 #include "wtf/Assertions.h" |
11 #include "wtf/Atomics.h" | 12 #include "wtf/Atomics.h" |
12 #include "wtf/Deque.h" | 13 #include "wtf/Deque.h" |
13 #include "wtf/HashCountedSet.h" | 14 #include "wtf/HashCountedSet.h" |
14 #include "wtf/HashMap.h" | 15 #include "wtf/HashMap.h" |
15 #include "wtf/HashSet.h" | 16 #include "wtf/HashSet.h" |
16 #include "wtf/HashTable.h" | 17 #include "wtf/HashTable.h" |
17 #include "wtf/LinkedHashSet.h" | 18 #include "wtf/LinkedHashSet.h" |
18 #include "wtf/ListHashSet.h" | 19 #include "wtf/ListHashSet.h" |
19 #include "wtf/TypeTraits.h" | 20 #include "wtf/TypeTraits.h" |
20 #include "wtf/Vector.h" | 21 #include "wtf/Vector.h" |
21 | 22 |
22 namespace blink { | 23 namespace blink { |
23 | 24 |
24 // This is a static-only class used as a trait on collections to make them heap | 25 // This is a static-only class used as a trait on collections to make them heap |
25 // allocated. However see also HeapListHashSetAllocator. | 26 // allocated. However see also HeapListHashSetAllocator. |
26 class PLATFORM_EXPORT HeapAllocator { | 27 class PLATFORM_EXPORT HeapAllocator { |
| 28 STATIC_ONLY(HeapAllocator); |
27 public: | 29 public: |
28 using Visitor = blink::Visitor; | 30 using Visitor = blink::Visitor; |
29 static const bool isGarbageCollected = true; | 31 static const bool isGarbageCollected = true; |
30 | 32 |
31 template<typename T> | 33 template<typename T> |
32 static size_t quantizedSize(size_t count) | 34 static size_t quantizedSize(size_t count) |
33 { | 35 { |
34 RELEASE_ASSERT(count <= maxHeapObjectSize / sizeof(T)); | 36 RELEASE_ASSERT(count <= maxHeapObjectSize / sizeof(T)); |
35 return Heap::allocationSizeFromSize(count * sizeof(T)) - sizeof(HeapObje
ctHeader); | 37 return Heap::allocationSizeFromSize(count * sizeof(T)) - sizeof(HeapObje
ctHeader); |
36 } | 38 } |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 TraceCollectionIfEnabled<WTF::NeedsTracingTrait<WTF::HashTraits<Value>>::val
ue, WTF::NoWeakHandlingInCollections, WTF::WeakPointersActWeak, Value, WTF::Hash
Traits<Value>>::trace(visitor, value); | 195 TraceCollectionIfEnabled<WTF::NeedsTracingTrait<WTF::HashTraits<Value>>::val
ue, WTF::NoWeakHandlingInCollections, WTF::WeakPointersActWeak, Value, WTF::Hash
Traits<Value>>::trace(visitor, value); |
194 } | 196 } |
195 | 197 |
196 // The inline capacity is just a dummy template argument to match the off-heap | 198 // The inline capacity is just a dummy template argument to match the off-heap |
197 // allocator. | 199 // allocator. |
198 // This inherits from the static-only HeapAllocator trait class, but we do | 200 // This inherits from the static-only HeapAllocator trait class, but we do |
199 // declare pointers to instances. These pointers are always null, and no | 201 // declare pointers to instances. These pointers are always null, and no |
200 // objects are instantiated. | 202 // objects are instantiated. |
201 template<typename ValueArg, size_t inlineCapacity> | 203 template<typename ValueArg, size_t inlineCapacity> |
202 class HeapListHashSetAllocator : public HeapAllocator { | 204 class HeapListHashSetAllocator : public HeapAllocator { |
| 205 DISALLOW_NEW(); |
203 public: | 206 public: |
204 using TableAllocator = HeapAllocator; | 207 using TableAllocator = HeapAllocator; |
205 using Node = WTF::ListHashSetNode<ValueArg, HeapListHashSetAllocator>; | 208 using Node = WTF::ListHashSetNode<ValueArg, HeapListHashSetAllocator>; |
206 | 209 |
207 class AllocatorProvider { | 210 class AllocatorProvider { |
| 211 DISALLOW_NEW(); |
208 public: | 212 public: |
209 // For the heap allocation we don't need an actual allocator object, so | 213 // For the heap allocation we don't need an actual allocator object, so |
210 // we just return null. | 214 // we just return null. |
211 HeapListHashSetAllocator* get() const { return 0; } | 215 HeapListHashSetAllocator* get() const { return 0; } |
212 | 216 |
213 // No allocator object is needed. | 217 // No allocator object is needed. |
214 void createAllocatorIfNeeded() { } | 218 void createAllocatorIfNeeded() { } |
215 void releaseAllocator() { } | 219 void releaseAllocator() { } |
216 | 220 |
217 // There is no allocator object in the HeapListHashSet (unlike in the | 221 // There is no allocator object in the HeapListHashSet (unlike in the |
(...skipping 15 matching lines...) Expand all Loading... |
233 } | 237 } |
234 | 238 |
235 template<typename VisitorDispatcher> | 239 template<typename VisitorDispatcher> |
236 static void traceValue(VisitorDispatcher visitor, Node* node) | 240 static void traceValue(VisitorDispatcher visitor, Node* node) |
237 { | 241 { |
238 traceListHashSetValue(visitor, node->m_value); | 242 traceListHashSetValue(visitor, node->m_value); |
239 } | 243 } |
240 }; | 244 }; |
241 | 245 |
242 template<typename T, typename Traits = WTF::VectorTraits<T>> class HeapVectorBac
king { | 246 template<typename T, typename Traits = WTF::VectorTraits<T>> class HeapVectorBac
king { |
| 247 DISALLOW_NEW(); |
243 public: | 248 public: |
244 static void finalize(void* pointer); | 249 static void finalize(void* pointer); |
245 void finalizeGarbageCollectedObject() { finalize(this); } | 250 void finalizeGarbageCollectedObject() { finalize(this); } |
246 }; | 251 }; |
247 | 252 |
248 template<typename T, typename Traits> | 253 template<typename T, typename Traits> |
249 void HeapVectorBacking<T, Traits>::finalize(void* pointer) | 254 void HeapVectorBacking<T, Traits>::finalize(void* pointer) |
250 { | 255 { |
251 static_assert(Traits::needsDestruction, "Only vector buffers with items requ
iring destruction should be finalized"); | 256 static_assert(Traits::needsDestruction, "Only vector buffers with items requ
iring destruction should be finalized"); |
252 // See the comment in HeapVectorBacking::trace. | 257 // See the comment in HeapVectorBacking::trace. |
(...skipping 17 matching lines...) Expand all Loading... |
270 buffer[i].~T(); | 275 buffer[i].~T(); |
271 } | 276 } |
272 } else { | 277 } else { |
273 for (unsigned i = 0; i < length; ++i) { | 278 for (unsigned i = 0; i < length; ++i) { |
274 buffer[i].~T(); | 279 buffer[i].~T(); |
275 } | 280 } |
276 } | 281 } |
277 } | 282 } |
278 | 283 |
279 template<typename Table> class HeapHashTableBacking { | 284 template<typename Table> class HeapHashTableBacking { |
| 285 DISALLOW_NEW(); |
280 public: | 286 public: |
281 static void finalize(void* pointer); | 287 static void finalize(void* pointer); |
282 void finalizeGarbageCollectedObject() { finalize(this); } | 288 void finalizeGarbageCollectedObject() { finalize(this); } |
283 }; | 289 }; |
284 | 290 |
285 template<typename Table> | 291 template<typename Table> |
286 void HeapHashTableBacking<Table>::finalize(void* pointer) | 292 void HeapHashTableBacking<Table>::finalize(void* pointer) |
287 { | 293 { |
288 using Value = typename Table::ValueType; | 294 using Value = typename Table::ValueType; |
289 ASSERT(!WTF::IsTriviallyDestructible<Value>::value); | 295 ASSERT(!WTF::IsTriviallyDestructible<Value>::value); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 : Deque<T, inlineCapacity, HeapAllocator>(other) | 395 : Deque<T, inlineCapacity, HeapAllocator>(other) |
390 { | 396 { |
391 } | 397 } |
392 }; | 398 }; |
393 | 399 |
394 } // namespace blink | 400 } // namespace blink |
395 | 401 |
396 namespace WTF { | 402 namespace WTF { |
397 | 403 |
398 template <typename T> struct VectorTraits<blink::Member<T>> : VectorTraitsBase<b
link::Member<T>> { | 404 template <typename T> struct VectorTraits<blink::Member<T>> : VectorTraitsBase<b
link::Member<T>> { |
| 405 STATIC_ONLY(VectorTraits); |
399 static const bool needsDestruction = false; | 406 static const bool needsDestruction = false; |
400 static const bool canInitializeWithMemset = true; | 407 static const bool canInitializeWithMemset = true; |
401 static const bool canClearUnusedSlotsWithMemset = true; | 408 static const bool canClearUnusedSlotsWithMemset = true; |
402 static const bool canMoveWithMemcpy = true; | 409 static const bool canMoveWithMemcpy = true; |
403 }; | 410 }; |
404 | 411 |
405 template <typename T> struct VectorTraits<blink::WeakMember<T>> : VectorTraitsBa
se<blink::WeakMember<T>> { | 412 template <typename T> struct VectorTraits<blink::WeakMember<T>> : VectorTraitsBa
se<blink::WeakMember<T>> { |
| 413 STATIC_ONLY(VectorTraits); |
406 static const bool needsDestruction = false; | 414 static const bool needsDestruction = false; |
407 static const bool canInitializeWithMemset = true; | 415 static const bool canInitializeWithMemset = true; |
408 static const bool canClearUnusedSlotsWithMemset = true; | 416 static const bool canClearUnusedSlotsWithMemset = true; |
409 static const bool canMoveWithMemcpy = true; | 417 static const bool canMoveWithMemcpy = true; |
410 }; | 418 }; |
411 | 419 |
412 template <typename T> struct VectorTraits<blink::UntracedMember<T>> : VectorTrai
tsBase<blink::UntracedMember<T>> { | 420 template <typename T> struct VectorTraits<blink::UntracedMember<T>> : VectorTrai
tsBase<blink::UntracedMember<T>> { |
| 421 STATIC_ONLY(VectorTraits); |
413 static const bool needsDestruction = false; | 422 static const bool needsDestruction = false; |
414 static const bool canInitializeWithMemset = true; | 423 static const bool canInitializeWithMemset = true; |
415 static const bool canClearUnusedSlotsWithMemset = true; | 424 static const bool canClearUnusedSlotsWithMemset = true; |
416 static const bool canMoveWithMemcpy = true; | 425 static const bool canMoveWithMemcpy = true; |
417 }; | 426 }; |
418 | 427 |
419 template <typename T> struct VectorTraits<blink::HeapVector<T, 0>> : VectorTrait
sBase<blink::HeapVector<T, 0>> { | 428 template <typename T> struct VectorTraits<blink::HeapVector<T, 0>> : VectorTrait
sBase<blink::HeapVector<T, 0>> { |
| 429 STATIC_ONLY(VectorTraits); |
420 static const bool needsDestruction = false; | 430 static const bool needsDestruction = false; |
421 static const bool canInitializeWithMemset = true; | 431 static const bool canInitializeWithMemset = true; |
422 static const bool canClearUnusedSlotsWithMemset = true; | 432 static const bool canClearUnusedSlotsWithMemset = true; |
423 static const bool canMoveWithMemcpy = true; | 433 static const bool canMoveWithMemcpy = true; |
424 }; | 434 }; |
425 | 435 |
426 template <typename T> struct VectorTraits<blink::HeapDeque<T, 0>> : VectorTraits
Base<blink::HeapDeque<T, 0>> { | 436 template <typename T> struct VectorTraits<blink::HeapDeque<T, 0>> : VectorTraits
Base<blink::HeapDeque<T, 0>> { |
| 437 STATIC_ONLY(VectorTraits); |
427 static const bool needsDestruction = false; | 438 static const bool needsDestruction = false; |
428 static const bool canInitializeWithMemset = true; | 439 static const bool canInitializeWithMemset = true; |
429 static const bool canClearUnusedSlotsWithMemset = true; | 440 static const bool canClearUnusedSlotsWithMemset = true; |
430 static const bool canMoveWithMemcpy = true; | 441 static const bool canMoveWithMemcpy = true; |
431 }; | 442 }; |
432 | 443 |
433 template <typename T, size_t inlineCapacity> struct VectorTraits<blink::HeapVect
or<T, inlineCapacity>> : VectorTraitsBase<blink::HeapVector<T, inlineCapacity>>
{ | 444 template <typename T, size_t inlineCapacity> struct VectorTraits<blink::HeapVect
or<T, inlineCapacity>> : VectorTraitsBase<blink::HeapVector<T, inlineCapacity>>
{ |
| 445 STATIC_ONLY(VectorTraits); |
434 static const bool needsDestruction = VectorTraits<T>::needsDestruction; | 446 static const bool needsDestruction = VectorTraits<T>::needsDestruction; |
435 static const bool canInitializeWithMemset = VectorTraits<T>::canInitializeWi
thMemset; | 447 static const bool canInitializeWithMemset = VectorTraits<T>::canInitializeWi
thMemset; |
436 static const bool canClearUnusedSlotsWithMemset = VectorTraits<T>::canClearU
nusedSlotsWithMemset; | 448 static const bool canClearUnusedSlotsWithMemset = VectorTraits<T>::canClearU
nusedSlotsWithMemset; |
437 static const bool canMoveWithMemcpy = VectorTraits<T>::canMoveWithMemcpy; | 449 static const bool canMoveWithMemcpy = VectorTraits<T>::canMoveWithMemcpy; |
438 }; | 450 }; |
439 | 451 |
440 template <typename T, size_t inlineCapacity> struct VectorTraits<blink::HeapDequ
e<T, inlineCapacity>> : VectorTraitsBase<blink::HeapDeque<T, inlineCapacity>> { | 452 template <typename T, size_t inlineCapacity> struct VectorTraits<blink::HeapDequ
e<T, inlineCapacity>> : VectorTraitsBase<blink::HeapDeque<T, inlineCapacity>> { |
| 453 STATIC_ONLY(VectorTraits); |
441 static const bool needsDestruction = VectorTraits<T>::needsDestruction; | 454 static const bool needsDestruction = VectorTraits<T>::needsDestruction; |
442 static const bool canInitializeWithMemset = VectorTraits<T>::canInitializeWi
thMemset; | 455 static const bool canInitializeWithMemset = VectorTraits<T>::canInitializeWi
thMemset; |
443 static const bool canClearUnusedSlotsWithMemset = VectorTraits<T>::canClearU
nusedSlotsWithMemset; | 456 static const bool canClearUnusedSlotsWithMemset = VectorTraits<T>::canClearU
nusedSlotsWithMemset; |
444 static const bool canMoveWithMemcpy = VectorTraits<T>::canMoveWithMemcpy; | 457 static const bool canMoveWithMemcpy = VectorTraits<T>::canMoveWithMemcpy; |
445 }; | 458 }; |
446 | 459 |
447 template<typename T> struct HashTraits<blink::Member<T>> : SimpleClassHashTraits
<blink::Member<T>> { | 460 template<typename T> struct HashTraits<blink::Member<T>> : SimpleClassHashTraits
<blink::Member<T>> { |
| 461 STATIC_ONLY(HashTraits); |
448 // FIXME: The distinction between PeekInType and PassInType is there for | 462 // FIXME: The distinction between PeekInType and PassInType is there for |
449 // the sake of the reference counting handles. When they are gone the two | 463 // the sake of the reference counting handles. When they are gone the two |
450 // types can be merged into PassInType. | 464 // types can be merged into PassInType. |
451 // FIXME: Implement proper const'ness for iterator types. Requires support | 465 // FIXME: Implement proper const'ness for iterator types. Requires support |
452 // in the marking Visitor. | 466 // in the marking Visitor. |
453 using PeekInType = RawPtr<T>; | 467 using PeekInType = RawPtr<T>; |
454 using PassInType = RawPtr<T>; | 468 using PassInType = RawPtr<T>; |
455 using IteratorGetType = blink::Member<T>*; | 469 using IteratorGetType = blink::Member<T>*; |
456 using IteratorConstGetType = const blink::Member<T>*; | 470 using IteratorConstGetType = const blink::Member<T>*; |
457 using IteratorReferenceType = blink::Member<T>&; | 471 using IteratorReferenceType = blink::Member<T>&; |
458 using IteratorConstReferenceType = const blink::Member<T>&; | 472 using IteratorConstReferenceType = const blink::Member<T>&; |
459 static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { r
eturn *x; } | 473 static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { r
eturn *x; } |
460 static IteratorConstReferenceType getToReferenceConstConversion(IteratorCons
tGetType x) { return *x; } | 474 static IteratorConstReferenceType getToReferenceConstConversion(IteratorCons
tGetType x) { return *x; } |
461 // FIXME: Similarly, there is no need for a distinction between PeekOutType | 475 // FIXME: Similarly, there is no need for a distinction between PeekOutType |
462 // and PassOutType without reference counting. | 476 // and PassOutType without reference counting. |
463 using PeekOutType = T*; | 477 using PeekOutType = T*; |
464 using PassOutType = T*; | 478 using PassOutType = T*; |
465 | 479 |
466 template<typename U> | 480 template<typename U> |
467 static void store(const U& value, blink::Member<T>& storage) { storage = val
ue; } | 481 static void store(const U& value, blink::Member<T>& storage) { storage = val
ue; } |
468 | 482 |
469 static PeekOutType peek(const blink::Member<T>& value) { return value; } | 483 static PeekOutType peek(const blink::Member<T>& value) { return value; } |
470 static PassOutType passOut(const blink::Member<T>& value) { return value; } | 484 static PassOutType passOut(const blink::Member<T>& value) { return value; } |
471 }; | 485 }; |
472 | 486 |
473 template<typename T> struct HashTraits<blink::WeakMember<T>> : SimpleClassHashTr
aits<blink::WeakMember<T>> { | 487 template<typename T> struct HashTraits<blink::WeakMember<T>> : SimpleClassHashTr
aits<blink::WeakMember<T>> { |
| 488 STATIC_ONLY(HashTraits); |
474 static const bool needsDestruction = false; | 489 static const bool needsDestruction = false; |
475 // FIXME: The distinction between PeekInType and PassInType is there for | 490 // FIXME: The distinction between PeekInType and PassInType is there for |
476 // the sake of the reference counting handles. When they are gone the two | 491 // the sake of the reference counting handles. When they are gone the two |
477 // types can be merged into PassInType. | 492 // types can be merged into PassInType. |
478 // FIXME: Implement proper const'ness for iterator types. Requires support | 493 // FIXME: Implement proper const'ness for iterator types. Requires support |
479 // in the marking Visitor. | 494 // in the marking Visitor. |
480 using PeekInType = RawPtr<T>; | 495 using PeekInType = RawPtr<T>; |
481 using PassInType = RawPtr<T>; | 496 using PassInType = RawPtr<T>; |
482 using IteratorGetType = blink::WeakMember<T>*; | 497 using IteratorGetType = blink::WeakMember<T>*; |
483 using IteratorConstGetType = const blink::WeakMember<T>*; | 498 using IteratorConstGetType = const blink::WeakMember<T>*; |
(...skipping 17 matching lines...) Expand all Loading... |
501 { | 516 { |
502 if (strongify == WeakPointersActStrong) { | 517 if (strongify == WeakPointersActStrong) { |
503 visitor->trace(weakMember.get()); // Strongified visit. | 518 visitor->trace(weakMember.get()); // Strongified visit. |
504 return false; | 519 return false; |
505 } | 520 } |
506 return !blink::Heap::isHeapObjectAlive(weakMember); | 521 return !blink::Heap::isHeapObjectAlive(weakMember); |
507 } | 522 } |
508 }; | 523 }; |
509 | 524 |
510 template<typename T> struct HashTraits<blink::UntracedMember<T>> : SimpleClassHa
shTraits<blink::UntracedMember<T>> { | 525 template<typename T> struct HashTraits<blink::UntracedMember<T>> : SimpleClassHa
shTraits<blink::UntracedMember<T>> { |
| 526 STATIC_ONLY(HashTraits); |
511 static const bool needsDestruction = false; | 527 static const bool needsDestruction = false; |
512 // FIXME: The distinction between PeekInType and PassInType is there for | 528 // FIXME: The distinction between PeekInType and PassInType is there for |
513 // the sake of the reference counting handles. When they are gone the two | 529 // the sake of the reference counting handles. When they are gone the two |
514 // types can be merged into PassInType. | 530 // types can be merged into PassInType. |
515 // FIXME: Implement proper const'ness for iterator types. | 531 // FIXME: Implement proper const'ness for iterator types. |
516 using PeekInType = RawPtr<T>; | 532 using PeekInType = RawPtr<T>; |
517 using PassInType = RawPtr<T>; | 533 using PassInType = RawPtr<T>; |
518 using IteratorGetType = blink::UntracedMember<T>*; | 534 using IteratorGetType = blink::UntracedMember<T>*; |
519 using IteratorConstGetType = const blink::UntracedMember<T>*; | 535 using IteratorConstGetType = const blink::UntracedMember<T>*; |
520 using IteratorReferenceType = blink::UntracedMember<T>&; | 536 using IteratorReferenceType = blink::UntracedMember<T>&; |
521 using IteratorConstReferenceType = const blink::UntracedMember<T>&; | 537 using IteratorConstReferenceType = const blink::UntracedMember<T>&; |
522 static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { r
eturn *x; } | 538 static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { r
eturn *x; } |
523 static IteratorConstReferenceType getToReferenceConstConversion(IteratorCons
tGetType x) { return *x; } | 539 static IteratorConstReferenceType getToReferenceConstConversion(IteratorCons
tGetType x) { return *x; } |
524 // FIXME: Similarly, there is no need for a distinction between PeekOutType | 540 // FIXME: Similarly, there is no need for a distinction between PeekOutType |
525 // and PassOutType without reference counting. | 541 // and PassOutType without reference counting. |
526 using PeekOutType = T*; | 542 using PeekOutType = T*; |
527 using PassOutType = T*; | 543 using PassOutType = T*; |
528 | 544 |
529 template<typename U> | 545 template<typename U> |
530 static void store(const U& value, blink::UntracedMember<T>& storage) { stora
ge = value; } | 546 static void store(const U& value, blink::UntracedMember<T>& storage) { stora
ge = value; } |
531 | 547 |
532 static PeekOutType peek(const blink::UntracedMember<T>& value) { return valu
e; } | 548 static PeekOutType peek(const blink::UntracedMember<T>& value) { return valu
e; } |
533 static PassOutType passOut(const blink::UntracedMember<T>& value) { return v
alue; } | 549 static PassOutType passOut(const blink::UntracedMember<T>& value) { return v
alue; } |
534 }; | 550 }; |
535 | 551 |
536 template<typename T, size_t inlineCapacity> | 552 template<typename T, size_t inlineCapacity> |
537 struct NeedsTracing<ListHashSetNode<T, blink::HeapListHashSetAllocator<T, inline
Capacity>> *> { | 553 struct NeedsTracing<ListHashSetNode<T, blink::HeapListHashSetAllocator<T, inline
Capacity>> *> { |
| 554 STATIC_ONLY(NeedsTracing); |
538 static_assert(sizeof(T), "T must be fully defined"); | 555 static_assert(sizeof(T), "T must be fully defined"); |
539 // All heap allocated node pointers need visiting to keep the nodes alive, | 556 // All heap allocated node pointers need visiting to keep the nodes alive, |
540 // regardless of whether they contain pointers to other heap allocated | 557 // regardless of whether they contain pointers to other heap allocated |
541 // objects. | 558 // objects. |
542 static const bool value = true; | 559 static const bool value = true; |
543 }; | 560 }; |
544 | 561 |
545 } // namespace WTF | 562 } // namespace WTF |
546 | 563 |
547 #endif | 564 #endif |
OLD | NEW |