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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 #include "wtf/LeakAnnotations.h" | 42 #include "wtf/LeakAnnotations.h" |
43 #include "wtf/PassOwnPtr.h" | 43 #include "wtf/PassOwnPtr.h" |
44 #if ENABLE(GC_PROFILE_MARKING) | 44 #if ENABLE(GC_PROFILE_MARKING) |
45 #include "wtf/HashMap.h" | 45 #include "wtf/HashMap.h" |
46 #include "wtf/HashSet.h" | 46 #include "wtf/HashSet.h" |
47 #include "wtf/text/StringBuilder.h" | 47 #include "wtf/text/StringBuilder.h" |
48 #include "wtf/text/StringHash.h" | 48 #include "wtf/text/StringHash.h" |
49 #include <stdio.h> | 49 #include <stdio.h> |
50 #include <utility> | 50 #include <utility> |
51 #endif | 51 #endif |
52 #if ENABLE(GC_PROFILE_HEAP) | 52 #if ENABLE(GC_PROFILE_HEAP) || ENABLE(GC_PROFILE_FREE_LIST) || ENABLE(GC_PROFILE
_MARKING) |
53 #include "platform/TracedValue.h" | 53 #include "platform/TracedValue.h" |
54 #endif | 54 #endif |
55 | 55 |
56 #if OS(POSIX) | 56 #if OS(POSIX) |
57 #include <sys/mman.h> | 57 #include <sys/mman.h> |
58 #include <unistd.h> | 58 #include <unistd.h> |
59 #elif OS(WIN) | 59 #elif OS(WIN) |
60 #include <windows.h> | 60 #include <windows.h> |
61 #endif | 61 #endif |
62 | 62 |
63 namespace blink { | 63 namespace blink { |
64 | 64 |
| 65 struct AgeHistogram { |
| 66 int data[8]; |
| 67 }; |
| 68 |
| 69 typedef HashMap<String, AgeHistogram> ObjectAgeMap; |
| 70 |
| 71 static ObjectAgeMap& uom() |
| 72 { |
| 73 static ObjectAgeMap uomap; |
| 74 return uomap; |
| 75 } |
| 76 |
| 77 static Mutex& uomMutex() |
| 78 { |
| 79 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); |
| 80 return mutex; |
| 81 } |
| 82 |
| 83 static ObjectAgeMap& mom() |
| 84 { |
| 85 static ObjectAgeMap momap; |
| 86 return momap; |
| 87 } |
| 88 |
| 89 static Mutex& momMutex() |
| 90 { |
| 91 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); |
| 92 return mutex; |
| 93 } |
| 94 |
65 #if ENABLE(GC_PROFILE_MARKING) | 95 #if ENABLE(GC_PROFILE_MARKING) |
66 static String classOf(const void* object) | 96 static String classOf(const void* object) |
67 { | 97 { |
68 const GCInfo* gcInfo = Heap::findGCInfo(reinterpret_cast<Address>(const_cast
<void*>(object))); | 98 const GCInfo* gcInfo = Heap::findGCInfo(reinterpret_cast<Address>(const_cast
<void*>(object))); |
69 if (gcInfo) | 99 if (gcInfo) |
70 return gcInfo->m_className; | 100 return gcInfo->m_className; |
71 | 101 |
72 return "unknown"; | 102 return "unknown"; |
73 } | 103 } |
74 #endif | 104 #endif |
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 FinalizedHeapObjectHeader* header = | 664 FinalizedHeapObjectHeader* header = |
635 reinterpret_cast<FinalizedHeapObjectHeader*>(addr - finalizedHeaderSize)
; | 665 reinterpret_cast<FinalizedHeapObjectHeader*>(addr - finalizedHeaderSize)
; |
636 return header; | 666 return header; |
637 } | 667 } |
638 | 668 |
639 template<typename Header> | 669 template<typename Header> |
640 ThreadHeap<Header>::ThreadHeap(ThreadState* state, int index) | 670 ThreadHeap<Header>::ThreadHeap(ThreadState* state, int index) |
641 : m_currentAllocationPoint(0) | 671 : m_currentAllocationPoint(0) |
642 , m_remainingAllocationSize(0) | 672 , m_remainingAllocationSize(0) |
643 , m_lastRemainingAllocationSize(0) | 673 , m_lastRemainingAllocationSize(0) |
| 674 #if ENABLE(GC_PROFILE_FREE_LIST) |
| 675 , m_totalAllocationSize(0.0) |
| 676 , m_allocationCount(0) |
| 677 , m_inlineAllocationCount(0) |
| 678 #endif |
644 , m_firstPage(0) | 679 , m_firstPage(0) |
645 , m_firstLargeObject(0) | 680 , m_firstLargeObject(0) |
646 , m_firstPageAllocatedDuringSweeping(0) | 681 , m_firstPageAllocatedDuringSweeping(0) |
647 , m_lastPageAllocatedDuringSweeping(0) | 682 , m_lastPageAllocatedDuringSweeping(0) |
648 , m_firstLargeObjectAllocatedDuringSweeping(0) | 683 , m_firstLargeObjectAllocatedDuringSweeping(0) |
649 , m_lastLargeObjectAllocatedDuringSweeping(0) | 684 , m_lastLargeObjectAllocatedDuringSweeping(0) |
650 , m_threadState(state) | 685 , m_threadState(state) |
651 , m_index(index) | 686 , m_index(index) |
652 , m_numberOfNormalPages(0) | 687 , m_numberOfNormalPages(0) |
653 , m_promptlyFreedCount(0) | 688 , m_promptlyFreedCount(0) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 if (m_lastRemainingAllocationSize > remainingAllocationSize()) { | 728 if (m_lastRemainingAllocationSize > remainingAllocationSize()) { |
694 Heap::increaseAllocatedObjectSize(m_lastRemainingAllocationSize - remain
ingAllocationSize()); | 729 Heap::increaseAllocatedObjectSize(m_lastRemainingAllocationSize - remain
ingAllocationSize()); |
695 m_lastRemainingAllocationSize = remainingAllocationSize(); | 730 m_lastRemainingAllocationSize = remainingAllocationSize(); |
696 } | 731 } |
697 ASSERT(m_lastRemainingAllocationSize == remainingAllocationSize()); | 732 ASSERT(m_lastRemainingAllocationSize == remainingAllocationSize()); |
698 } | 733 } |
699 | 734 |
700 template<typename Header> | 735 template<typename Header> |
701 Address ThreadHeap<Header>::outOfLineAllocate(size_t payloadSize, size_t allocat
ionSize, const GCInfo* gcInfo) | 736 Address ThreadHeap<Header>::outOfLineAllocate(size_t payloadSize, size_t allocat
ionSize, const GCInfo* gcInfo) |
702 { | 737 { |
| 738 #if ENABLE(GC_PROFILE_FREE_LIST) |
| 739 m_threadState->snapshotFreeListIfNecessary(); |
| 740 #endif |
703 ASSERT(allocationSize > remainingAllocationSize()); | 741 ASSERT(allocationSize > remainingAllocationSize()); |
704 if (allocationSize > blinkPageSize / 2) | 742 if (allocationSize > blinkPageSize / 2) |
705 return allocateLargeObject(allocationSize, gcInfo); | 743 return allocateLargeObject(allocationSize, gcInfo); |
706 | 744 |
707 updateRemainingAllocationSize(); | 745 updateRemainingAllocationSize(); |
708 if (threadState()->shouldGC()) { | 746 if (threadState()->shouldGC()) { |
709 if (threadState()->shouldForceConservativeGC()) | 747 if (threadState()->shouldForceConservativeGC()) |
710 Heap::collectGarbage(ThreadState::HeapPointersOnStack); | 748 Heap::collectGarbage(ThreadState::HeapPointersOnStack); |
711 else | 749 else |
712 threadState()->setGCRequested(); | 750 threadState()->setGCRequested(); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 const GCInfo* ThreadHeap<Header>::findGCInfoOfLargeObject(Address address) | 830 const GCInfo* ThreadHeap<Header>::findGCInfoOfLargeObject(Address address) |
793 { | 831 { |
794 for (LargeObject<Header>* largeObject = m_firstLargeObject; largeObject; lar
geObject = largeObject->next()) { | 832 for (LargeObject<Header>* largeObject = m_firstLargeObject; largeObject; lar
geObject = largeObject->next()) { |
795 if (largeObject->contains(address)) | 833 if (largeObject->contains(address)) |
796 return largeObject->gcInfo(); | 834 return largeObject->gcInfo(); |
797 } | 835 } |
798 return 0; | 836 return 0; |
799 } | 837 } |
800 #endif | 838 #endif |
801 | 839 |
| 840 #if ENABLE(GC_PROFILE_FREE_LIST) |
| 841 template<typename Header> |
| 842 void ThreadHeap<Header>::snapshotFreeList(TracedValue* json) |
| 843 { |
| 844 json->setDouble("totalAllocationSize", m_totalAllocationSize); |
| 845 json->setDouble("inlineAllocationRate", static_cast<double>(m_inlineAllocati
onCount) / m_allocationCount); |
| 846 json->setInteger("inlineAllocationCount", m_inlineAllocationCount); |
| 847 json->setInteger("allocationCount", m_allocationCount); |
| 848 if (m_setAllocationPointCount > 0) { |
| 849 json->setDouble("averageAllocationPointSize", static_cast<double>(m_alloca
tionPointSizeSum) / m_setAllocationPointCount); |
| 850 } |
| 851 m_allocationPointSizeSum = 0; |
| 852 m_setAllocationPointCount = 0; |
| 853 size_t pageCount = 0; |
| 854 size_t totalPageSize = 0; |
| 855 for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) { |
| 856 ++pageCount; |
| 857 totalPageSize += page->payloadSize(); |
| 858 } |
| 859 json->setInteger("pageCount", pageCount); |
| 860 json->setInteger("totalPageSize", totalPageSize); |
| 861 size_t bucketSizes[blinkPageSizeLog2]; |
| 862 size_t bucketTotalSizes[blinkPageSizeLog2]; |
| 863 size_t freeSize = 0; |
| 864 m_freeList.countBucketSizes(bucketSizes, bucketTotalSizes, &freeSize); |
| 865 json->setInteger("freeSize", freeSize); |
| 866 json->beginArray("bucketSizes"); |
| 867 for (size_t i = 0; i < blinkPageSizeLog2; ++i) { |
| 868 json->pushInteger(bucketSizes[i]); |
| 869 } |
| 870 json->endArray(); |
| 871 json->beginArray("bucketTotalSizes"); |
| 872 for (size_t i = 0; i < blinkPageSizeLog2; ++i) { |
| 873 json->pushInteger(bucketTotalSizes[i]); |
| 874 } |
| 875 json->endArray(); |
| 876 } |
| 877 #endif |
| 878 |
802 #if ENABLE(GC_PROFILE_HEAP) | 879 #if ENABLE(GC_PROFILE_HEAP) |
803 #define GC_PROFILE_HEAP_PAGE_SNAPSHOT_THRESHOLD 0 | 880 #define GC_PROFILE_HEAP_PAGE_SNAPSHOT_THRESHOLD 0 |
804 template<typename Header> | 881 template<typename Header> |
805 void ThreadHeap<Header>::snapshot(TracedValue* json, ThreadState::SnapshotInfo*
info) | 882 void ThreadHeap<Header>::snapshot(TracedValue* json, ThreadState::SnapshotInfo*
info) |
806 { | 883 { |
807 size_t previousPageCount = info->pageCount; | 884 size_t previousPageCount = info->pageCount; |
808 | 885 |
809 json->beginArray("pages"); | 886 json->beginArray("pages"); |
810 for (HeapPage<Header>* page = m_firstPage; page; page = page->next(), ++info
->pageCount) { | 887 for (HeapPage<Header>* page = m_firstPage; page; page = page->next(), ++info
->pageCount) { |
811 // FIXME: To limit the size of the snapshot we only output "threshold" m
any page snapshots. | 888 // FIXME: To limit the size of the snapshot we only output "threshold" m
any page snapshots. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 return; | 936 return; |
860 #endif | 937 #endif |
861 int index = bucketIndexForSize(size); | 938 int index = bucketIndexForSize(size); |
862 entry->link(&m_freeLists[index]); | 939 entry->link(&m_freeLists[index]); |
863 if (!m_lastFreeListEntries[index]) | 940 if (!m_lastFreeListEntries[index]) |
864 m_lastFreeListEntries[index] = entry; | 941 m_lastFreeListEntries[index] = entry; |
865 if (index > m_biggestFreeListIndex) | 942 if (index > m_biggestFreeListIndex) |
866 m_biggestFreeListIndex = index; | 943 m_biggestFreeListIndex = index; |
867 } | 944 } |
868 | 945 |
| 946 #if ENABLE(GC_PROFILE_FREE_LIST) |
| 947 template<typename Header> |
| 948 void FreeList<Header>::countBucketSizes(size_t sizes[], size_t totalSizes[], siz
e_t* freeSize) const |
| 949 { |
| 950 *freeSize = 0; |
| 951 for (size_t i = 0; i < blinkPageSizeLog2; i++) { |
| 952 sizes[i] = 0; |
| 953 totalSizes[i] = 0; |
| 954 FreeListEntry* entry = m_freeLists[i]; |
| 955 while (entry) { |
| 956 ++sizes[i]; |
| 957 *freeSize += entry->size(); |
| 958 totalSizes[i] += entry->size(); |
| 959 entry = entry->next(); |
| 960 } |
| 961 } |
| 962 } |
| 963 #endif |
| 964 |
869 template<typename Header> | 965 template<typename Header> |
870 bool ThreadHeap<Header>::expandObject(Header* header, size_t newSize) | 966 bool ThreadHeap<Header>::expandObject(Header* header, size_t newSize) |
871 { | 967 { |
872 ASSERT(header->payloadSize() < newSize); | 968 ASSERT(header->payloadSize() < newSize); |
873 size_t allocationSize = allocationSizeFromSize(newSize); | 969 size_t allocationSize = allocationSizeFromSize(newSize); |
874 ASSERT(allocationSize > header->size()); | 970 ASSERT(allocationSize > header->size()); |
875 size_t expandSize = allocationSize - header->size(); | 971 size_t expandSize = allocationSize - header->size(); |
876 if (header->payloadEnd() == m_currentAllocationPoint && expandSize <= m_rema
iningAllocationSize) { | 972 if (header->payloadEnd() == m_currentAllocationPoint && expandSize <= m_rema
iningAllocationSize) { |
877 m_currentAllocationPoint += expandSize; | 973 m_currentAllocationPoint += expandSize; |
878 m_remainingAllocationSize -= expandSize; | 974 m_remainingAllocationSize -= expandSize; |
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1437 // STRICT_ASAN_FINALIZATION_CHECKING turns on poisoning of all objects during | 1533 // STRICT_ASAN_FINALIZATION_CHECKING turns on poisoning of all objects during |
1438 // sweeping to catch cases where dead objects touch each other. This is not | 1534 // sweeping to catch cases where dead objects touch each other. This is not |
1439 // turned on by default because it also triggers for cases that are safe. | 1535 // turned on by default because it also triggers for cases that are safe. |
1440 // Examples of such safe cases are context life cycle observers and timers | 1536 // Examples of such safe cases are context life cycle observers and timers |
1441 // embedded in garbage collected objects. | 1537 // embedded in garbage collected objects. |
1442 #define STRICT_ASAN_FINALIZATION_CHECKING 0 | 1538 #define STRICT_ASAN_FINALIZATION_CHECKING 0 |
1443 | 1539 |
1444 template<typename Header> | 1540 template<typename Header> |
1445 void ThreadHeap<Header>::sweep() | 1541 void ThreadHeap<Header>::sweep() |
1446 { | 1542 { |
| 1543 for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) { |
| 1544 page->countUnmarkedObjects(); |
| 1545 } |
1447 ASSERT(isConsistentForSweeping()); | 1546 ASSERT(isConsistentForSweeping()); |
1448 #if defined(ADDRESS_SANITIZER) && STRICT_ASAN_FINALIZATION_CHECKING | 1547 #if defined(ADDRESS_SANITIZER) && STRICT_ASAN_FINALIZATION_CHECKING |
1449 // When using ASan do a pre-sweep where all unmarked objects are | 1548 // When using ASan do a pre-sweep where all unmarked objects are |
1450 // poisoned before calling their finalizer methods. This can catch | 1549 // poisoned before calling their finalizer methods. This can catch |
1451 // the case where the finalizer of an object tries to modify | 1550 // the case where the finalizer of an object tries to modify |
1452 // another object as part of finalization. | 1551 // another object as part of finalization. |
1453 for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) | 1552 for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) |
1454 page->poisonUnmarkedObjects(); | 1553 page->poisonUnmarkedObjects(); |
1455 #endif | 1554 #endif |
1456 sweepNormalPages(); | 1555 sweepNormalPages(); |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1828 Header* header = reinterpret_cast<Header*>(headerAddress); | 1927 Header* header = reinterpret_cast<Header*>(headerAddress); |
1829 ASSERT(header->size() < blinkPagePayloadSize()); | 1928 ASSERT(header->size() < blinkPagePayloadSize()); |
1830 | 1929 |
1831 if (!header->isFree() && !header->isMarked()) | 1930 if (!header->isFree() && !header->isMarked()) |
1832 ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); | 1931 ASAN_POISON_MEMORY_REGION(header->payload(), header->payloadSize()); |
1833 headerAddress += header->size(); | 1932 headerAddress += header->size(); |
1834 } | 1933 } |
1835 } | 1934 } |
1836 #endif | 1935 #endif |
1837 | 1936 |
| 1937 template<typename Header> |
| 1938 void HeapPage<Header>::countUnmarkedObjects() |
| 1939 { |
| 1940 MutexLocker locker(uomMutex()); |
| 1941 for (Address headerAddress = payload(); headerAddress < end(); ) { |
| 1942 Header* header = reinterpret_cast<Header*>(headerAddress); |
| 1943 ASSERT(header->size() < blinkPagePayloadSize()); |
| 1944 |
| 1945 if (!header->isFree() && !header->isMarked()) { |
| 1946 String className(classOf(header->payload())); |
| 1947 ObjectAgeMap::AddResult result = uom().add(className, AgeHistogram()
); |
| 1948 result.storedValue->value.data[header->age()]++; |
| 1949 } |
| 1950 headerAddress += header->size(); |
| 1951 } |
| 1952 } |
| 1953 |
1838 template<> | 1954 template<> |
1839 inline void HeapPage<FinalizedHeapObjectHeader>::finalize(FinalizedHeapObjectHea
der* header) | 1955 inline void HeapPage<FinalizedHeapObjectHeader>::finalize(FinalizedHeapObjectHea
der* header) |
1840 { | 1956 { |
1841 header->finalize(); | 1957 header->finalize(); |
1842 } | 1958 } |
1843 | 1959 |
1844 template<> | 1960 template<> |
1845 inline void HeapPage<HeapObjectHeader>::finalize(HeapObjectHeader* header) | 1961 inline void HeapPage<HeapObjectHeader>::finalize(HeapObjectHeader* header) |
1846 { | 1962 { |
1847 ASSERT(gcInfo()); | 1963 ASSERT(gcInfo()); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1989 // when doing weakness for ephemerons. Hence we only check | 2105 // when doing weakness for ephemerons. Hence we only check |
1990 // when called within. | 2106 // when called within. |
1991 ASSERT(!ThreadState::isAnyThreadInGC() || Heap::containedInHeapOrOrp
hanedPage(header)); | 2107 ASSERT(!ThreadState::isAnyThreadInGC() || Heap::containedInHeapOrOrp
hanedPage(header)); |
1992 } | 2108 } |
1993 #endif | 2109 #endif |
1994 ASSERT(objectPointer); | 2110 ASSERT(objectPointer); |
1995 if (header->isMarked()) | 2111 if (header->isMarked()) |
1996 return; | 2112 return; |
1997 header->mark(); | 2113 header->mark(); |
1998 #if ENABLE(GC_PROFILE_MARKING) | 2114 #if ENABLE(GC_PROFILE_MARKING) |
| 2115 header->incAge(); |
| 2116 |
1999 MutexLocker locker(objectGraphMutex()); | 2117 MutexLocker locker(objectGraphMutex()); |
2000 String className(classOf(objectPointer)); | 2118 String className(classOf(objectPointer)); |
2001 { | 2119 { |
2002 LiveObjectMap::AddResult result = currentlyLive().add(className, Liv
eObjectSet()); | 2120 LiveObjectMap::AddResult result = currentlyLive().add(className, Liv
eObjectSet()); |
2003 result.storedValue->value.add(reinterpret_cast<uintptr_t>(objectPoin
ter)); | 2121 result.storedValue->value.add(reinterpret_cast<uintptr_t>(objectPoin
ter)); |
2004 } | 2122 } |
| 2123 { |
| 2124 MutexLocker locker(momMutex()); |
| 2125 ObjectAgeMap::AddResult result = mom().add(className, AgeHistogram()
); |
| 2126 result.storedValue->value.data[header->age()]++; |
| 2127 } |
2005 ObjectGraph::AddResult result = objectGraph().add(reinterpret_cast<uintp
tr_t>(objectPointer), std::make_pair(reinterpret_cast<uintptr_t>(m_hostObject),
m_hostName)); | 2128 ObjectGraph::AddResult result = objectGraph().add(reinterpret_cast<uintp
tr_t>(objectPointer), std::make_pair(reinterpret_cast<uintptr_t>(m_hostObject),
m_hostName)); |
2006 ASSERT(result.isNewEntry); | 2129 ASSERT(result.isNewEntry); |
2007 // fprintf(stderr, "%s[%p] -> %s[%p]\n", m_hostName.ascii().data(), m_ho
stObject, className.ascii().data(), objectPointer); | 2130 // fprintf(stderr, "%s[%p] -> %s[%p]\n", m_hostName.ascii().data(), m_ho
stObject, className.ascii().data(), objectPointer); |
2008 #endif | 2131 #endif |
2009 if (callback) | 2132 if (callback) |
2010 Heap::pushTraceCallback(m_markingStack, const_cast<void*>(objectPoin
ter), callback); | 2133 Heap::pushTraceCallback(m_markingStack, const_cast<void*>(objectPoin
ter), callback); |
2011 } | 2134 } |
2012 | 2135 |
2013 virtual void mark(HeapObjectHeader* header, TraceCallback callback) override | 2136 virtual void mark(HeapObjectHeader* header, TraceCallback callback) override |
2014 { | 2137 { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2091 } | 2214 } |
2092 | 2215 |
2093 previouslyLive().swap(currentlyLive()); | 2216 previouslyLive().swap(currentlyLive()); |
2094 currentlyLive().clear(); | 2217 currentlyLive().clear(); |
2095 | 2218 |
2096 for (HashSet<uintptr_t>::iterator it = objectsToFindPath().begin(), end
= objectsToFindPath().end(); it != end; ++it) { | 2219 for (HashSet<uintptr_t>::iterator it = objectsToFindPath().begin(), end
= objectsToFindPath().end(); it != end; ++it) { |
2097 dumpPathToObjectFromObjectGraph(objectGraph(), *it); | 2220 dumpPathToObjectFromObjectGraph(objectGraph(), *it); |
2098 } | 2221 } |
2099 } | 2222 } |
2100 | 2223 |
| 2224 void reportMarkingStats() |
| 2225 { |
| 2226 MutexLocker locker(momMutex()); |
| 2227 RefPtr<TracedValue> json = TracedValue::create(); |
| 2228 for (ObjectAgeMap::iterator it = mom().begin(), end = mom().end(); it !=
end; ++it) { |
| 2229 json->beginArray(it->key.ascii().data()); |
| 2230 for (size_t i = 0; i < 8; ++i) { |
| 2231 json->pushInteger(it->value.data[i]); |
| 2232 } |
| 2233 json->endArray(); |
| 2234 } |
| 2235 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("blink_gc", "MarkingStats", (unsigne
d long long)0, json.release()); |
| 2236 mom().clear(); |
| 2237 } |
| 2238 |
2101 static void reportStillAlive(LiveObjectSet current, LiveObjectSet previous) | 2239 static void reportStillAlive(LiveObjectSet current, LiveObjectSet previous) |
2102 { | 2240 { |
2103 int count = 0; | 2241 int count = 0; |
2104 | 2242 |
2105 fprintf(stderr, " [previously %u]", previous.size()); | 2243 fprintf(stderr, " [previously %u]", previous.size()); |
2106 for (LiveObjectSet::iterator it = current.begin(), end = current.end();
it != end; ++it) { | 2244 for (LiveObjectSet::iterator it = current.begin(), end = current.end();
it != end; ++it) { |
2107 if (previous.find(*it) == previous.end()) | 2245 if (previous.find(*it) == previous.end()) |
2108 continue; | 2246 continue; |
2109 count++; | 2247 count++; |
2110 } | 2248 } |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2448 #endif | 2586 #endif |
2449 | 2587 |
2450 void Heap::prepareForGC() | 2588 void Heap::prepareForGC() |
2451 { | 2589 { |
2452 ASSERT(ThreadState::isAnyThreadInGC()); | 2590 ASSERT(ThreadState::isAnyThreadInGC()); |
2453 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); | 2591 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); |
2454 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) | 2592 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) |
2455 (*it)->prepareForGC(); | 2593 (*it)->prepareForGC(); |
2456 } | 2594 } |
2457 | 2595 |
| 2596 void Heap::reportSweepingStats() |
| 2597 { |
| 2598 MutexLocker locker(uomMutex()); |
| 2599 RefPtr<TracedValue> json = TracedValue::create(); |
| 2600 for (ObjectAgeMap::iterator it = uom().begin(), end = uom().end(); it != end
; ++it) { |
| 2601 json->beginArray(it->key.ascii().data()); |
| 2602 for (size_t i = 0; i < 8; ++i) { |
| 2603 json->pushInteger(it->value.data[i]); |
| 2604 } |
| 2605 json->endArray(); |
| 2606 } |
| 2607 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("blink_gc", "SweepingStats", (unsigned l
ong long)0, json.release()); |
| 2608 uom().clear(); |
| 2609 } |
| 2610 |
2458 void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::Cause
OfGC cause) | 2611 void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::Cause
OfGC cause) |
2459 { | 2612 { |
2460 ThreadState* state = ThreadState::current(); | 2613 ThreadState* state = ThreadState::current(); |
2461 state->clearGCRequested(); | 2614 state->clearGCRequested(); |
2462 | 2615 |
| 2616 #if ENABLE(GC_PROFILE_FREE_LIST) |
| 2617 state->snapshotFreeListIfNecessary(); |
| 2618 #endif |
| 2619 |
2463 GCScope gcScope(stackState); | 2620 GCScope gcScope(stackState); |
2464 // Check if we successfully parked the other threads. If not we bail out of
the GC. | 2621 // Check if we successfully parked the other threads. If not we bail out of
the GC. |
2465 if (!gcScope.allThreadsParked()) { | 2622 if (!gcScope.allThreadsParked()) { |
2466 ThreadState::current()->setGCRequested(); | 2623 ThreadState::current()->setGCRequested(); |
2467 return; | 2624 return; |
2468 } | 2625 } |
2469 | 2626 |
2470 if (state->isMainThread()) | 2627 if (state->isMainThread()) |
2471 ScriptForbiddenScope::enter(); | 2628 ScriptForbiddenScope::enter(); |
2472 | 2629 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2510 | 2667 |
2511 postMarkingProcessing(); | 2668 postMarkingProcessing(); |
2512 globalWeakProcessing(); | 2669 globalWeakProcessing(); |
2513 | 2670 |
2514 // Now we can delete all orphaned pages because there are no dangling | 2671 // Now we can delete all orphaned pages because there are no dangling |
2515 // pointers to the orphaned pages. (If we have such dangling pointers, | 2672 // pointers to the orphaned pages. (If we have such dangling pointers, |
2516 // we should have crashed during marking before getting here.) | 2673 // we should have crashed during marking before getting here.) |
2517 orphanedPagePool()->decommitOrphanedPages(); | 2674 orphanedPagePool()->decommitOrphanedPages(); |
2518 | 2675 |
2519 #if ENABLE(GC_PROFILE_MARKING) | 2676 #if ENABLE(GC_PROFILE_MARKING) |
2520 static_cast<MarkingVisitor*>(s_markingVisitor)->reportStats(); | 2677 //static_cast<MarkingVisitor*>(s_markingVisitor)->reportStats(); |
| 2678 static_cast<MarkingVisitor*>(s_markingVisitor)->reportMarkingStats(); |
2521 #endif | 2679 #endif |
2522 | 2680 |
2523 if (Platform::current()) { | 2681 if (Platform::current()) { |
2524 Platform::current()->histogramCustomCounts("BlinkGC.CollectGarbage", WTF
::currentTimeMS() - timeStamp, 0, 10 * 1000, 50); | 2682 Platform::current()->histogramCustomCounts("BlinkGC.CollectGarbage", WTF
::currentTimeMS() - timeStamp, 0, 10 * 1000, 50); |
2525 Platform::current()->histogramCustomCounts("BlinkGC.TotalObjectSpace", H
eap::allocatedObjectSize() / 1024, 0, 4 * 1024 * 1024, 50); | 2683 Platform::current()->histogramCustomCounts("BlinkGC.TotalObjectSpace", H
eap::allocatedObjectSize() / 1024, 0, 4 * 1024 * 1024, 50); |
2526 Platform::current()->histogramCustomCounts("BlinkGC.TotalAllocatedSpace"
, Heap::allocatedSpace() / 1024, 0, 4 * 1024 * 1024, 50); | 2684 Platform::current()->histogramCustomCounts("BlinkGC.TotalAllocatedSpace"
, Heap::allocatedSpace() / 1024, 0, 4 * 1024 * 1024, 50); |
2527 } | 2685 } |
2528 | 2686 |
2529 if (state->isMainThread()) | 2687 if (state->isMainThread()) |
2530 ScriptForbiddenScope::exit(); | 2688 ScriptForbiddenScope::exit(); |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2860 bool Heap::s_shutdownCalled = false; | 3018 bool Heap::s_shutdownCalled = false; |
2861 bool Heap::s_lastGCWasConservative = false; | 3019 bool Heap::s_lastGCWasConservative = false; |
2862 FreePagePool* Heap::s_freePagePool; | 3020 FreePagePool* Heap::s_freePagePool; |
2863 OrphanedPagePool* Heap::s_orphanedPagePool; | 3021 OrphanedPagePool* Heap::s_orphanedPagePool; |
2864 Heap::RegionTree* Heap::s_regionTree = 0; | 3022 Heap::RegionTree* Heap::s_regionTree = 0; |
2865 size_t Heap::s_allocatedObjectSize = 0; | 3023 size_t Heap::s_allocatedObjectSize = 0; |
2866 size_t Heap::s_allocatedSpace = 0; | 3024 size_t Heap::s_allocatedSpace = 0; |
2867 size_t Heap::s_markedObjectSize = 0; | 3025 size_t Heap::s_markedObjectSize = 0; |
2868 | 3026 |
2869 } // namespace blink | 3027 } // namespace blink |
OLD | NEW |