OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 19 matching lines...) Expand all Loading... |
30 | 30 |
31 #ifndef Heap_h | 31 #ifndef Heap_h |
32 #define Heap_h | 32 #define Heap_h |
33 | 33 |
34 #include "platform/PlatformExport.h" | 34 #include "platform/PlatformExport.h" |
35 #include "platform/heap/AddressSanitizer.h" | 35 #include "platform/heap/AddressSanitizer.h" |
36 #include "platform/heap/ThreadState.h" | 36 #include "platform/heap/ThreadState.h" |
37 #include "platform/heap/Visitor.h" | 37 #include "platform/heap/Visitor.h" |
38 #include "public/platform/WebThread.h" | 38 #include "public/platform/WebThread.h" |
39 #include "wtf/Assertions.h" | 39 #include "wtf/Assertions.h" |
| 40 #include "wtf/Atomics.h" |
40 #include "wtf/HashCountedSet.h" | 41 #include "wtf/HashCountedSet.h" |
41 #include "wtf/LinkedHashSet.h" | 42 #include "wtf/LinkedHashSet.h" |
42 #include "wtf/ListHashSet.h" | 43 #include "wtf/ListHashSet.h" |
43 #include "wtf/OwnPtr.h" | 44 #include "wtf/OwnPtr.h" |
44 #include "wtf/PassRefPtr.h" | 45 #include "wtf/PassRefPtr.h" |
45 #include "wtf/ThreadSafeRefCounted.h" | 46 #include "wtf/ThreadSafeRefCounted.h" |
46 | 47 |
47 #include <stdint.h> | 48 #include <stdint.h> |
48 | 49 |
49 // FIXME: We temporarily disable parallel marking because the current | 50 // FIXME: We temporarily disable parallel marking because the current |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 #endif | 110 #endif |
110 | 111 |
111 const int numberOfPagesToConsiderForCoalescing = 100; | 112 const int numberOfPagesToConsiderForCoalescing = 100; |
112 | 113 |
113 enum CallbackInvocationMode { | 114 enum CallbackInvocationMode { |
114 GlobalMarking, | 115 GlobalMarking, |
115 ThreadLocalMarking, | 116 ThreadLocalMarking, |
116 }; | 117 }; |
117 | 118 |
118 class CallbackStack; | 119 class CallbackStack; |
119 class HeapStats; | |
120 class PageMemory; | 120 class PageMemory; |
121 template<ThreadAffinity affinity> class ThreadLocalPersistents; | 121 template<ThreadAffinity affinity> class ThreadLocalPersistents; |
122 template<typename T, typename RootsAccessor = ThreadLocalPersistents<ThreadingTr
ait<T>::Affinity > > class Persistent; | 122 template<typename T, typename RootsAccessor = ThreadLocalPersistents<ThreadingTr
ait<T>::Affinity > > class Persistent; |
123 | 123 |
124 #if ENABLE(GC_PROFILE_HEAP) | 124 #if ENABLE(GC_PROFILE_HEAP) |
125 class TracedValue; | 125 class TracedValue; |
126 #endif | 126 #endif |
127 | 127 |
128 PLATFORM_EXPORT size_t osPageSize(); | 128 PLATFORM_EXPORT size_t osPageSize(); |
129 | 129 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 size_t payloadSize() { return heapObjectHeader()->payloadSize(); } | 256 size_t payloadSize() { return heapObjectHeader()->payloadSize(); } |
257 | 257 |
258 Header* heapObjectHeader() | 258 Header* heapObjectHeader() |
259 { | 259 { |
260 Address headerAddress = address() + sizeof(LargeHeapObject<Header>) + he
aderPadding<Header>(); | 260 Address headerAddress = address() + sizeof(LargeHeapObject<Header>) + he
aderPadding<Header>(); |
261 return reinterpret_cast<Header*>(headerAddress); | 261 return reinterpret_cast<Header*>(headerAddress); |
262 } | 262 } |
263 | 263 |
264 bool isMarked(); | 264 bool isMarked(); |
265 void unmark(); | 265 void unmark(); |
266 void getStatsForTesting(HeapStats&); | 266 size_t objectPayloadSizeForTesting(); |
267 void mark(Visitor*); | 267 void mark(Visitor*); |
268 void finalize(); | 268 void finalize(); |
269 void setDeadMark(); | 269 void setDeadMark(); |
270 virtual void markOrphaned() | 270 virtual void markOrphaned() |
271 { | 271 { |
272 // Zap the payload with a recognizable value to detect any incorrect | 272 // Zap the payload with a recognizable value to detect any incorrect |
273 // cross thread pointer usage. | 273 // cross thread pointer usage. |
274 memset(payload(), orphanedZapValue, payloadSize()); | 274 memset(payload(), orphanedZapValue, payloadSize()); |
275 BaseHeapPage::markOrphaned(); | 275 BaseHeapPage::markOrphaned(); |
276 } | 276 } |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 return address() + sizeof(*this) + headerPadding<Header>(); | 530 return address() + sizeof(*this) + headerPadding<Header>(); |
531 } | 531 } |
532 | 532 |
533 static size_t payloadSize() | 533 static size_t payloadSize() |
534 { | 534 { |
535 return (blinkPagePayloadSize() - sizeof(HeapPage) - headerPadding<Header
>()) & ~allocationMask; | 535 return (blinkPagePayloadSize() - sizeof(HeapPage) - headerPadding<Header
>()) & ~allocationMask; |
536 } | 536 } |
537 | 537 |
538 Address end() { return payload() + payloadSize(); } | 538 Address end() { return payload() + payloadSize(); } |
539 | 539 |
540 void getStatsForTesting(HeapStats&); | 540 size_t objectPayloadSizeForTesting(); |
541 void clearLiveAndMarkDead(); | 541 void clearLiveAndMarkDead(); |
542 void sweep(HeapStats*, ThreadHeap<Header>*); | 542 void sweep(ThreadHeap<Header>*); |
543 void clearObjectStartBitMap(); | 543 void clearObjectStartBitMap(); |
544 void finalize(Header*); | 544 void finalize(Header*); |
545 virtual void checkAndMarkPointer(Visitor*, Address) override; | 545 virtual void checkAndMarkPointer(Visitor*, Address) override; |
546 #if ENABLE(GC_PROFILE_MARKING) | 546 #if ENABLE(GC_PROFILE_MARKING) |
547 const GCInfo* findGCInfo(Address) override; | 547 const GCInfo* findGCInfo(Address) override; |
548 #endif | 548 #endif |
549 #if ENABLE(GC_PROFILE_HEAP) | 549 #if ENABLE(GC_PROFILE_HEAP) |
550 virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*); | 550 virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*); |
551 #endif | 551 #endif |
552 | 552 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 #if ENABLE(GC_PROFILE_MARKING) | 699 #if ENABLE(GC_PROFILE_MARKING) |
700 virtual const GCInfo* findGCInfoOfLargeHeapObject(Address) = 0; | 700 virtual const GCInfo* findGCInfoOfLargeHeapObject(Address) = 0; |
701 #endif | 701 #endif |
702 | 702 |
703 #if ENABLE(GC_PROFILE_HEAP) | 703 #if ENABLE(GC_PROFILE_HEAP) |
704 virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*) = 0; | 704 virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*) = 0; |
705 #endif | 705 #endif |
706 | 706 |
707 // Sweep this part of the Blink heap. This finalizes dead objects | 707 // Sweep this part of the Blink heap. This finalizes dead objects |
708 // and builds freelists for all the unused memory. | 708 // and builds freelists for all the unused memory. |
709 virtual void sweep(HeapStats*) = 0; | 709 virtual void sweep() = 0; |
710 virtual void postSweepProcessing() = 0; | 710 virtual void postSweepProcessing() = 0; |
711 | 711 |
712 virtual void clearFreeLists() = 0; | 712 virtual void clearFreeLists() = 0; |
713 virtual void clearLiveAndMarkDead() = 0; | 713 virtual void clearLiveAndMarkDead() = 0; |
714 | 714 |
715 virtual void makeConsistentForSweeping() = 0; | 715 virtual void makeConsistentForSweeping() = 0; |
716 #if ENABLE(ASSERT) | 716 #if ENABLE(ASSERT) |
717 virtual bool isConsistentForSweeping() = 0; | 717 virtual bool isConsistentForSweeping() = 0; |
718 #endif | 718 #endif |
719 virtual void getStatsForTesting(HeapStats&) = 0; | 719 virtual size_t objectPayloadSizeForTesting() = 0; |
720 | 720 |
721 virtual void updateRemainingAllocationSize() = 0; | 721 virtual void updateRemainingAllocationSize() = 0; |
722 | 722 |
723 virtual void prepareHeapForTermination() = 0; | 723 virtual void prepareHeapForTermination() = 0; |
724 | 724 |
725 virtual int normalPageCount() = 0; | 725 virtual int normalPageCount() = 0; |
726 | 726 |
727 virtual PassOwnPtr<BaseHeap> split(int normalPages) = 0; | 727 virtual PassOwnPtr<BaseHeap> split(int normalPages) = 0; |
728 virtual void merge(PassOwnPtr<BaseHeap> other) = 0; | 728 virtual void merge(PassOwnPtr<BaseHeap> other) = 0; |
729 }; | 729 }; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 virtual void cleanupPages() override; | 769 virtual void cleanupPages() override; |
770 | 770 |
771 virtual BaseHeapPage* heapPageFromAddress(Address) override; | 771 virtual BaseHeapPage* heapPageFromAddress(Address) override; |
772 #if ENABLE(GC_PROFILE_MARKING) | 772 #if ENABLE(GC_PROFILE_MARKING) |
773 virtual const GCInfo* findGCInfoOfLargeHeapObject(Address) override; | 773 virtual const GCInfo* findGCInfoOfLargeHeapObject(Address) override; |
774 #endif | 774 #endif |
775 #if ENABLE(GC_PROFILE_HEAP) | 775 #if ENABLE(GC_PROFILE_HEAP) |
776 virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*) override; | 776 virtual void snapshot(TracedValue*, ThreadState::SnapshotInfo*) override; |
777 #endif | 777 #endif |
778 | 778 |
779 virtual void sweep(HeapStats*) override; | 779 virtual void sweep() override; |
780 virtual void postSweepProcessing() override; | 780 virtual void postSweepProcessing() override; |
781 | 781 |
782 virtual void clearFreeLists() override; | 782 virtual void clearFreeLists() override; |
783 virtual void clearLiveAndMarkDead() override; | 783 virtual void clearLiveAndMarkDead() override; |
784 | 784 |
785 virtual void makeConsistentForSweeping() override; | 785 virtual void makeConsistentForSweeping() override; |
786 #if ENABLE(ASSERT) | 786 #if ENABLE(ASSERT) |
787 virtual bool isConsistentForSweeping() override; | 787 virtual bool isConsistentForSweeping() override; |
788 #endif | 788 #endif |
789 virtual void getStatsForTesting(HeapStats&) override; | 789 virtual size_t objectPayloadSizeForTesting() override; |
790 | 790 |
791 virtual void updateRemainingAllocationSize() override; | 791 virtual void updateRemainingAllocationSize() override; |
792 | 792 |
793 ThreadState* threadState() { return m_threadState; } | 793 ThreadState* threadState() { return m_threadState; } |
794 HeapStats& stats() { return m_threadState->stats(); } | |
795 | 794 |
796 void addToFreeList(Address address, size_t size) | 795 void addToFreeList(Address address, size_t size) |
797 { | 796 { |
798 ASSERT(heapPageFromAddress(address)); | 797 ASSERT(heapPageFromAddress(address)); |
799 ASSERT(heapPageFromAddress(address + size - 1)); | 798 ASSERT(heapPageFromAddress(address + size - 1)); |
800 m_freeList.addToFreeList(address, size); | 799 m_freeList.addToFreeList(address, size); |
801 } | 800 } |
802 | 801 |
803 inline Address allocate(size_t, const GCInfo*); | 802 inline Address allocate(size_t, const GCInfo*); |
804 inline static size_t roundedAllocationSize(size_t size) | 803 inline static size_t roundedAllocationSize(size_t size) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
838 bool allocateFromFreeList(size_t); | 837 bool allocateFromFreeList(size_t); |
839 | 838 |
840 void freeLargeObject(LargeHeapObject<Header>*, LargeHeapObject<Header>**); | 839 void freeLargeObject(LargeHeapObject<Header>*, LargeHeapObject<Header>**); |
841 void allocatePage(const GCInfo*); | 840 void allocatePage(const GCInfo*); |
842 | 841 |
843 #if ENABLE(ASSERT) | 842 #if ENABLE(ASSERT) |
844 bool pagesToBeSweptContains(Address); | 843 bool pagesToBeSweptContains(Address); |
845 bool pagesAllocatedDuringSweepingContains(Address); | 844 bool pagesAllocatedDuringSweepingContains(Address); |
846 #endif | 845 #endif |
847 | 846 |
848 void sweepNormalPages(HeapStats*); | 847 void sweepNormalPages(); |
849 void sweepLargePages(HeapStats*); | 848 void sweepLargePages(); |
850 bool coalesce(size_t); | 849 bool coalesce(size_t); |
851 | 850 |
852 Address m_currentAllocationPoint; | 851 Address m_currentAllocationPoint; |
853 size_t m_remainingAllocationSize; | 852 size_t m_remainingAllocationSize; |
854 size_t m_lastRemainingAllocationSize; | 853 size_t m_lastRemainingAllocationSize; |
855 | 854 |
856 HeapPage<Header>* m_firstPage; | 855 HeapPage<Header>* m_firstPage; |
857 LargeHeapObject<Header>* m_firstLargeHeapObject; | 856 LargeHeapObject<Header>* m_firstLargeHeapObject; |
858 | 857 |
859 HeapPage<Header>* m_firstPageAllocatedDuringSweeping; | 858 HeapPage<Header>* m_firstPageAllocatedDuringSweeping; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
960 static void dumpPathToObjectOnNextGC(void* p); | 959 static void dumpPathToObjectOnNextGC(void* p); |
961 | 960 |
962 // Forcibly find GCInfo of the object at Address. | 961 // Forcibly find GCInfo of the object at Address. |
963 // This is slow and should only be used for debug purposes. | 962 // This is slow and should only be used for debug purposes. |
964 // It involves finding the heap page and scanning the heap page for an objec
t header. | 963 // It involves finding the heap page and scanning the heap page for an objec
t header. |
965 static const GCInfo* findGCInfo(Address); | 964 static const GCInfo* findGCInfo(Address); |
966 | 965 |
967 static String createBacktraceString(); | 966 static String createBacktraceString(); |
968 #endif | 967 #endif |
969 | 968 |
970 static void getStatsForTesting(HeapStats*); | 969 static size_t objectPayloadSizeForTesting(); |
971 | 970 |
972 static void getHeapSpaceSize(uint64_t*, uint64_t*); | 971 static void getHeapSpaceSize(uint64_t*, uint64_t*); |
973 | 972 |
974 static void makeConsistentForSweeping(); | 973 static void makeConsistentForSweeping(); |
975 | 974 |
976 #if ENABLE(ASSERT) | 975 #if ENABLE(ASSERT) |
977 static bool isConsistentForSweeping(); | 976 static bool isConsistentForSweeping(); |
978 #endif | 977 #endif |
979 | 978 |
980 static void flushHeapDoesNotContainCache(); | 979 static void flushHeapDoesNotContainCache(); |
981 | 980 |
982 // Return true if the last GC found a pointer into a heap page | 981 // Return true if the last GC found a pointer into a heap page |
983 // during conservative scanning. | 982 // during conservative scanning. |
984 static bool lastGCWasConservative() { return s_lastGCWasConservative; } | 983 static bool lastGCWasConservative() { return s_lastGCWasConservative; } |
985 | 984 |
986 static FreePagePool* freePagePool() { return s_freePagePool; } | 985 static FreePagePool* freePagePool() { return s_freePagePool; } |
987 static OrphanedPagePool* orphanedPagePool() { return s_orphanedPagePool; } | 986 static OrphanedPagePool* orphanedPagePool() { return s_orphanedPagePool; } |
988 | 987 |
989 // This look-up uses the region search tree and a negative contains cache to | 988 // This look-up uses the region search tree and a negative contains cache to |
990 // provide an efficient mapping from arbitrary addresses to the containing | 989 // provide an efficient mapping from arbitrary addresses to the containing |
991 // heap-page if one exists. | 990 // heap-page if one exists. |
992 static BaseHeapPage* lookup(Address); | 991 static BaseHeapPage* lookup(Address); |
993 static void addPageMemoryRegion(PageMemoryRegion*); | 992 static void addPageMemoryRegion(PageMemoryRegion*); |
994 static void removePageMemoryRegion(PageMemoryRegion*); | 993 static void removePageMemoryRegion(PageMemoryRegion*); |
995 | 994 |
| 995 static void increaseAllocatedObjectSize(size_t delta) { atomicAdd(&s_allocat
edObjectSize, static_cast<long>(delta)); } |
| 996 static void decreaseAllocatedObjectSize(size_t delta) { atomicSubtract(&s_al
locatedObjectSize, static_cast<long>(delta)); } |
| 997 static size_t allocatedObjectSize() { return s_allocatedObjectSize; } |
| 998 static void increaseMarkedObjectSize(size_t delta) { atomicAdd(&s_markedObje
ctSize, static_cast<long>(delta)); } |
| 999 static size_t markedObjectSize() { return s_markedObjectSize; } |
| 1000 static void increaseAllocatedSpace(size_t delta) { atomicAdd(&s_allocatedSpa
ce, static_cast<long>(delta)); } |
| 1001 static void decreaseAllocatedSpace(size_t delta) { atomicSubtract(&s_allocat
edSpace, static_cast<long>(delta)); } |
| 1002 static size_t allocatedSpace() { return s_allocatedSpace; } |
| 1003 |
996 private: | 1004 private: |
997 // A RegionTree is a simple binary search tree of PageMemoryRegions sorted | 1005 // A RegionTree is a simple binary search tree of PageMemoryRegions sorted |
998 // by base addresses. | 1006 // by base addresses. |
999 class RegionTree { | 1007 class RegionTree { |
1000 public: | 1008 public: |
1001 explicit RegionTree(PageMemoryRegion* region) : m_region(region), m_left
(0), m_right(0) { } | 1009 explicit RegionTree(PageMemoryRegion* region) : m_region(region), m_left
(0), m_right(0) { } |
1002 ~RegionTree() | 1010 ~RegionTree() |
1003 { | 1011 { |
1004 delete m_left; | 1012 delete m_left; |
1005 delete m_right; | 1013 delete m_right; |
1006 } | 1014 } |
1007 PageMemoryRegion* lookup(Address); | 1015 PageMemoryRegion* lookup(Address); |
1008 static void add(RegionTree*, RegionTree**); | 1016 static void add(RegionTree*, RegionTree**); |
1009 static void remove(PageMemoryRegion*, RegionTree**); | 1017 static void remove(PageMemoryRegion*, RegionTree**); |
1010 private: | 1018 private: |
1011 PageMemoryRegion* m_region; | 1019 PageMemoryRegion* m_region; |
1012 RegionTree* m_left; | 1020 RegionTree* m_left; |
1013 RegionTree* m_right; | 1021 RegionTree* m_right; |
1014 }; | 1022 }; |
1015 | 1023 |
| 1024 static void resetAllocatedObjectSize() { ASSERT(ThreadState::isAnyThreadInGC
()); s_allocatedObjectSize = 0; } |
| 1025 static void resetMarkedObjectSize() { ASSERT(ThreadState::isAnyThreadInGC())
; s_markedObjectSize = 0; } |
| 1026 |
1016 static Visitor* s_markingVisitor; | 1027 static Visitor* s_markingVisitor; |
1017 static Vector<OwnPtr<WebThread>>* s_markingThreads; | 1028 static Vector<OwnPtr<WebThread>>* s_markingThreads; |
1018 static CallbackStack* s_markingStack; | 1029 static CallbackStack* s_markingStack; |
1019 static CallbackStack* s_postMarkingCallbackStack; | 1030 static CallbackStack* s_postMarkingCallbackStack; |
1020 static CallbackStack* s_weakCallbackStack; | 1031 static CallbackStack* s_weakCallbackStack; |
1021 static CallbackStack* s_ephemeronStack; | 1032 static CallbackStack* s_ephemeronStack; |
1022 static HeapDoesNotContainCache* s_heapDoesNotContainCache; | 1033 static HeapDoesNotContainCache* s_heapDoesNotContainCache; |
1023 static bool s_shutdownCalled; | 1034 static bool s_shutdownCalled; |
1024 static bool s_lastGCWasConservative; | 1035 static bool s_lastGCWasConservative; |
1025 static FreePagePool* s_freePagePool; | 1036 static FreePagePool* s_freePagePool; |
1026 static OrphanedPagePool* s_orphanedPagePool; | 1037 static OrphanedPagePool* s_orphanedPagePool; |
1027 static RegionTree* s_regionTree; | 1038 static RegionTree* s_regionTree; |
| 1039 static size_t s_allocatedSpace; |
| 1040 static size_t s_allocatedObjectSize; |
| 1041 static size_t s_markedObjectSize; |
1028 friend class ThreadState; | 1042 friend class ThreadState; |
1029 }; | 1043 }; |
1030 | 1044 |
1031 // The NoAllocationScope class is used in debug mode to catch unwanted | 1045 // The NoAllocationScope class is used in debug mode to catch unwanted |
1032 // allocations. E.g. allocations during GC. | 1046 // allocations. E.g. allocations during GC. |
1033 template<ThreadAffinity Affinity> | 1047 template<ThreadAffinity Affinity> |
1034 class NoAllocationScope { | 1048 class NoAllocationScope { |
1035 public: | 1049 public: |
1036 NoAllocationScope() : m_active(true) { enter(); } | 1050 NoAllocationScope() : m_active(true) { enter(); } |
1037 | 1051 |
(...skipping 1366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2404 template<typename T, size_t inlineCapacity> | 2418 template<typename T, size_t inlineCapacity> |
2405 struct GCInfoTrait<HeapVector<T, inlineCapacity> > : public GCInfoTrait<Vector<T
, inlineCapacity, HeapAllocator> > { }; | 2419 struct GCInfoTrait<HeapVector<T, inlineCapacity> > : public GCInfoTrait<Vector<T
, inlineCapacity, HeapAllocator> > { }; |
2406 template<typename T, size_t inlineCapacity> | 2420 template<typename T, size_t inlineCapacity> |
2407 struct GCInfoTrait<HeapDeque<T, inlineCapacity> > : public GCInfoTrait<Deque<T,
inlineCapacity, HeapAllocator> > { }; | 2421 struct GCInfoTrait<HeapDeque<T, inlineCapacity> > : public GCInfoTrait<Deque<T,
inlineCapacity, HeapAllocator> > { }; |
2408 template<typename T, typename U, typename V> | 2422 template<typename T, typename U, typename V> |
2409 struct GCInfoTrait<HeapHashCountedSet<T, U, V> > : public GCInfoTrait<HashCounte
dSet<T, U, V, HeapAllocator> > { }; | 2423 struct GCInfoTrait<HeapHashCountedSet<T, U, V> > : public GCInfoTrait<HashCounte
dSet<T, U, V, HeapAllocator> > { }; |
2410 | 2424 |
2411 } // namespace blink | 2425 } // namespace blink |
2412 | 2426 |
2413 #endif // Heap_h | 2427 #endif // Heap_h |
OLD | NEW |