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" | |
41 #include "wtf/HashCountedSet.h" | 40 #include "wtf/HashCountedSet.h" |
42 #include "wtf/LinkedHashSet.h" | 41 #include "wtf/LinkedHashSet.h" |
43 #include "wtf/ListHashSet.h" | 42 #include "wtf/ListHashSet.h" |
44 #include "wtf/OwnPtr.h" | 43 #include "wtf/OwnPtr.h" |
45 #include "wtf/PassRefPtr.h" | 44 #include "wtf/PassRefPtr.h" |
46 #include "wtf/ThreadSafeRefCounted.h" | 45 #include "wtf/ThreadSafeRefCounted.h" |
47 | 46 |
48 #include <stdint.h> | 47 #include <stdint.h> |
49 | 48 |
50 // FIXME: We temporarily disable parallel marking because the current | 49 // FIXME: We temporarily disable parallel marking because the current |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 #endif | 109 #endif |
111 | 110 |
112 const int numberOfPagesToConsiderForCoalescing = 100; | 111 const int numberOfPagesToConsiderForCoalescing = 100; |
113 | 112 |
114 enum CallbackInvocationMode { | 113 enum CallbackInvocationMode { |
115 GlobalMarking, | 114 GlobalMarking, |
116 ThreadLocalMarking, | 115 ThreadLocalMarking, |
117 }; | 116 }; |
118 | 117 |
119 class CallbackStack; | 118 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 size_t objectPayloadSizeForTesting(); | 266 void getStatsForTesting(HeapStats&); |
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 size_t objectPayloadSizeForTesting(); | 540 void getStatsForTesting(HeapStats&); |
541 void clearLiveAndMarkDead(); | 541 void clearLiveAndMarkDead(); |
542 void sweep(ThreadHeap<Header>*); | 542 void sweep(HeapStats*, 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() = 0; | 709 virtual void sweep(HeapStats*) = 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 size_t objectPayloadSizeForTesting() = 0; | 719 virtual void getStatsForTesting(HeapStats&) = 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() override; | 779 virtual void sweep(HeapStats*) 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 size_t objectPayloadSizeForTesting() override; | 789 virtual void getStatsForTesting(HeapStats&) 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(); } |
794 | 795 |
795 void addToFreeList(Address address, size_t size) | 796 void addToFreeList(Address address, size_t size) |
796 { | 797 { |
797 ASSERT(heapPageFromAddress(address)); | 798 ASSERT(heapPageFromAddress(address)); |
798 ASSERT(heapPageFromAddress(address + size - 1)); | 799 ASSERT(heapPageFromAddress(address + size - 1)); |
799 m_freeList.addToFreeList(address, size); | 800 m_freeList.addToFreeList(address, size); |
800 } | 801 } |
801 | 802 |
802 inline Address allocate(size_t, const GCInfo*); | 803 inline Address allocate(size_t, const GCInfo*); |
803 inline static size_t roundedAllocationSize(size_t size) | 804 inline static size_t roundedAllocationSize(size_t size) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
837 bool allocateFromFreeList(size_t); | 838 bool allocateFromFreeList(size_t); |
838 | 839 |
839 void freeLargeObject(LargeHeapObject<Header>*, LargeHeapObject<Header>**); | 840 void freeLargeObject(LargeHeapObject<Header>*, LargeHeapObject<Header>**); |
840 void allocatePage(const GCInfo*); | 841 void allocatePage(const GCInfo*); |
841 | 842 |
842 #if ENABLE(ASSERT) | 843 #if ENABLE(ASSERT) |
843 bool pagesToBeSweptContains(Address); | 844 bool pagesToBeSweptContains(Address); |
844 bool pagesAllocatedDuringSweepingContains(Address); | 845 bool pagesAllocatedDuringSweepingContains(Address); |
845 #endif | 846 #endif |
846 | 847 |
847 void sweepNormalPages(); | 848 void sweepNormalPages(HeapStats*); |
848 void sweepLargePages(); | 849 void sweepLargePages(HeapStats*); |
849 bool coalesce(size_t); | 850 bool coalesce(size_t); |
850 | 851 |
851 Address m_currentAllocationPoint; | 852 Address m_currentAllocationPoint; |
852 size_t m_remainingAllocationSize; | 853 size_t m_remainingAllocationSize; |
853 size_t m_lastRemainingAllocationSize; | 854 size_t m_lastRemainingAllocationSize; |
854 | 855 |
855 HeapPage<Header>* m_firstPage; | 856 HeapPage<Header>* m_firstPage; |
856 LargeHeapObject<Header>* m_firstLargeHeapObject; | 857 LargeHeapObject<Header>* m_firstLargeHeapObject; |
857 | 858 |
858 HeapPage<Header>* m_firstPageAllocatedDuringSweeping; | 859 HeapPage<Header>* m_firstPageAllocatedDuringSweeping; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 static void dumpPathToObjectOnNextGC(void* p); | 960 static void dumpPathToObjectOnNextGC(void* p); |
960 | 961 |
961 // Forcibly find GCInfo of the object at Address. | 962 // Forcibly find GCInfo of the object at Address. |
962 // This is slow and should only be used for debug purposes. | 963 // This is slow and should only be used for debug purposes. |
963 // It involves finding the heap page and scanning the heap page for an objec
t header. | 964 // It involves finding the heap page and scanning the heap page for an objec
t header. |
964 static const GCInfo* findGCInfo(Address); | 965 static const GCInfo* findGCInfo(Address); |
965 | 966 |
966 static String createBacktraceString(); | 967 static String createBacktraceString(); |
967 #endif | 968 #endif |
968 | 969 |
969 static size_t objectPayloadSizeForTesting(); | 970 static void getStatsForTesting(HeapStats*); |
970 | 971 |
971 static void getHeapSpaceSize(uint64_t*, uint64_t*); | 972 static void getHeapSpaceSize(uint64_t*, uint64_t*); |
972 | 973 |
973 static void makeConsistentForSweeping(); | 974 static void makeConsistentForSweeping(); |
974 | 975 |
975 #if ENABLE(ASSERT) | 976 #if ENABLE(ASSERT) |
976 static bool isConsistentForSweeping(); | 977 static bool isConsistentForSweeping(); |
977 #endif | 978 #endif |
978 | 979 |
979 static void flushHeapDoesNotContainCache(); | 980 static void flushHeapDoesNotContainCache(); |
980 | 981 |
981 // Return true if the last GC found a pointer into a heap page | 982 // Return true if the last GC found a pointer into a heap page |
982 // during conservative scanning. | 983 // during conservative scanning. |
983 static bool lastGCWasConservative() { return s_lastGCWasConservative; } | 984 static bool lastGCWasConservative() { return s_lastGCWasConservative; } |
984 | 985 |
985 static FreePagePool* freePagePool() { return s_freePagePool; } | 986 static FreePagePool* freePagePool() { return s_freePagePool; } |
986 static OrphanedPagePool* orphanedPagePool() { return s_orphanedPagePool; } | 987 static OrphanedPagePool* orphanedPagePool() { return s_orphanedPagePool; } |
987 | 988 |
988 // This look-up uses the region search tree and a negative contains cache to | 989 // This look-up uses the region search tree and a negative contains cache to |
989 // provide an efficient mapping from arbitrary addresses to the containing | 990 // provide an efficient mapping from arbitrary addresses to the containing |
990 // heap-page if one exists. | 991 // heap-page if one exists. |
991 static BaseHeapPage* lookup(Address); | 992 static BaseHeapPage* lookup(Address); |
992 static void addPageMemoryRegion(PageMemoryRegion*); | 993 static void addPageMemoryRegion(PageMemoryRegion*); |
993 static void removePageMemoryRegion(PageMemoryRegion*); | 994 static void removePageMemoryRegion(PageMemoryRegion*); |
994 | 995 |
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 | |
1004 private: | 996 private: |
1005 // A RegionTree is a simple binary search tree of PageMemoryRegions sorted | 997 // A RegionTree is a simple binary search tree of PageMemoryRegions sorted |
1006 // by base addresses. | 998 // by base addresses. |
1007 class RegionTree { | 999 class RegionTree { |
1008 public: | 1000 public: |
1009 explicit RegionTree(PageMemoryRegion* region) : m_region(region), m_left
(0), m_right(0) { } | 1001 explicit RegionTree(PageMemoryRegion* region) : m_region(region), m_left
(0), m_right(0) { } |
1010 ~RegionTree() | 1002 ~RegionTree() |
1011 { | 1003 { |
1012 delete m_left; | 1004 delete m_left; |
1013 delete m_right; | 1005 delete m_right; |
1014 } | 1006 } |
1015 PageMemoryRegion* lookup(Address); | 1007 PageMemoryRegion* lookup(Address); |
1016 static void add(RegionTree*, RegionTree**); | 1008 static void add(RegionTree*, RegionTree**); |
1017 static void remove(PageMemoryRegion*, RegionTree**); | 1009 static void remove(PageMemoryRegion*, RegionTree**); |
1018 private: | 1010 private: |
1019 PageMemoryRegion* m_region; | 1011 PageMemoryRegion* m_region; |
1020 RegionTree* m_left; | 1012 RegionTree* m_left; |
1021 RegionTree* m_right; | 1013 RegionTree* m_right; |
1022 }; | 1014 }; |
1023 | 1015 |
1024 static void resetAllocatedObjectSize() { ASSERT(ThreadState::isAnyThreadInGC
()); s_allocatedObjectSize = 0; } | |
1025 static void resetMarkedObjectSize() { ASSERT(ThreadState::isAnyThreadInGC())
; s_markedObjectSize = 0; } | |
1026 | |
1027 static Visitor* s_markingVisitor; | 1016 static Visitor* s_markingVisitor; |
1028 static Vector<OwnPtr<WebThread>>* s_markingThreads; | 1017 static Vector<OwnPtr<WebThread>>* s_markingThreads; |
1029 static CallbackStack* s_markingStack; | 1018 static CallbackStack* s_markingStack; |
1030 static CallbackStack* s_postMarkingCallbackStack; | 1019 static CallbackStack* s_postMarkingCallbackStack; |
1031 static CallbackStack* s_weakCallbackStack; | 1020 static CallbackStack* s_weakCallbackStack; |
1032 static CallbackStack* s_ephemeronStack; | 1021 static CallbackStack* s_ephemeronStack; |
1033 static HeapDoesNotContainCache* s_heapDoesNotContainCache; | 1022 static HeapDoesNotContainCache* s_heapDoesNotContainCache; |
1034 static bool s_shutdownCalled; | 1023 static bool s_shutdownCalled; |
1035 static bool s_lastGCWasConservative; | 1024 static bool s_lastGCWasConservative; |
1036 static FreePagePool* s_freePagePool; | 1025 static FreePagePool* s_freePagePool; |
1037 static OrphanedPagePool* s_orphanedPagePool; | 1026 static OrphanedPagePool* s_orphanedPagePool; |
1038 static RegionTree* s_regionTree; | 1027 static RegionTree* s_regionTree; |
1039 static size_t s_allocatedSpace; | |
1040 static size_t s_allocatedObjectSize; | |
1041 static size_t s_markedObjectSize; | |
1042 friend class ThreadState; | 1028 friend class ThreadState; |
1043 }; | 1029 }; |
1044 | 1030 |
1045 // The NoAllocationScope class is used in debug mode to catch unwanted | 1031 // The NoAllocationScope class is used in debug mode to catch unwanted |
1046 // allocations. E.g. allocations during GC. | 1032 // allocations. E.g. allocations during GC. |
1047 template<ThreadAffinity Affinity> | 1033 template<ThreadAffinity Affinity> |
1048 class NoAllocationScope { | 1034 class NoAllocationScope { |
1049 public: | 1035 public: |
1050 NoAllocationScope() : m_active(true) { enter(); } | 1036 NoAllocationScope() : m_active(true) { enter(); } |
1051 | 1037 |
(...skipping 1366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2418 template<typename T, size_t inlineCapacity> | 2404 template<typename T, size_t inlineCapacity> |
2419 struct GCInfoTrait<HeapVector<T, inlineCapacity> > : public GCInfoTrait<Vector<T
, inlineCapacity, HeapAllocator> > { }; | 2405 struct GCInfoTrait<HeapVector<T, inlineCapacity> > : public GCInfoTrait<Vector<T
, inlineCapacity, HeapAllocator> > { }; |
2420 template<typename T, size_t inlineCapacity> | 2406 template<typename T, size_t inlineCapacity> |
2421 struct GCInfoTrait<HeapDeque<T, inlineCapacity> > : public GCInfoTrait<Deque<T,
inlineCapacity, HeapAllocator> > { }; | 2407 struct GCInfoTrait<HeapDeque<T, inlineCapacity> > : public GCInfoTrait<Deque<T,
inlineCapacity, HeapAllocator> > { }; |
2422 template<typename T, typename U, typename V> | 2408 template<typename T, typename U, typename V> |
2423 struct GCInfoTrait<HeapHashCountedSet<T, U, V> > : public GCInfoTrait<HashCounte
dSet<T, U, V, HeapAllocator> > { }; | 2409 struct GCInfoTrait<HeapHashCountedSet<T, U, V> > : public GCInfoTrait<HashCounte
dSet<T, U, V, HeapAllocator> > { }; |
2424 | 2410 |
2425 } // namespace blink | 2411 } // namespace blink |
2426 | 2412 |
2427 #endif // Heap_h | 2413 #endif // Heap_h |
OLD | NEW |