| 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 |