Chromium Code Reviews| Index: Source/platform/heap/Heap.cpp |
| diff --git a/Source/platform/heap/Heap.cpp b/Source/platform/heap/Heap.cpp |
| index 3f1948e6cdd9fa8424962f288b751c04f063cfbe..6545b5f0914f6a6776a47860fd8c3698d21da050 100644 |
| --- a/Source/platform/heap/Heap.cpp |
| +++ b/Source/platform/heap/Heap.cpp |
| @@ -39,7 +39,7 @@ |
| #include "wtf/Assertions.h" |
| #include "wtf/LeakAnnotations.h" |
| #include "wtf/PassOwnPtr.h" |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| #include "wtf/HashMap.h" |
| #include "wtf/HashSet.h" |
| #include "wtf/text/StringBuilder.h" |
| @@ -47,6 +47,9 @@ |
| #include <stdio.h> |
| #include <utility> |
| #endif |
| +#if GC_PROFILE_HEAP |
| +#include "platform/TracedValue.h" |
| +#endif |
| #if OS(POSIX) |
| #include <sys/mman.h> |
| @@ -57,7 +60,7 @@ |
| namespace WebCore { |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| static String classOf(const void* object) |
| { |
| const GCInfo* gcInfo = Heap::findGCInfo(reinterpret_cast<Address>(const_cast<void*>(object))); |
| @@ -369,10 +372,10 @@ public: |
| , m_safePointScope(stackState) |
| , m_parkedAllThreads(false) |
| { |
| - TRACE_EVENT0("blink", "Heap::GCScope"); |
| + TRACE_EVENT0(GC_PROFILE_GROUP, "Heap::GCScope"); |
| const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); |
| if (m_state->isMainThread()) |
| - TRACE_EVENT_SET_SAMPLING_STATE("blink", "BlinkGCWaiting"); |
| + TRACE_EVENT_SET_SAMPLING_STATE(GC_PROFILE_GROUP, "BlinkGCWaiting"); |
| m_state->checkThread(); |
| @@ -505,7 +508,7 @@ void LargeHeapObject<Header>::checkAndMarkPointer(Visitor* visitor, Address addr |
| ASSERT(contains(address)); |
| if (!objectContains(address)) |
| return; |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| visitor->setHostInfo(&address, "stack"); |
| #endif |
| mark(visitor); |
| @@ -641,7 +644,7 @@ BaseHeapPage* ThreadHeap<Header>::heapPageFromAddress(Address address) |
| return 0; |
| } |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| template<typename Header> |
| const GCInfo* ThreadHeap<Header>::findGCInfoOfLargeHeapObject(Address address) |
| { |
| @@ -653,6 +656,43 @@ const GCInfo* ThreadHeap<Header>::findGCInfoOfLargeHeapObject(Address address) |
| } |
| #endif |
| +#if GC_PROFILE_HEAP |
| +template<typename Header> |
| +void ThreadHeap<Header>::snapshot(TracedDictionaryBase* json, ThreadState::SnapshotInfo* info) |
| +{ |
| + size_t previousPageCount = info->pageCount; |
| + |
| + TracedArray<TracedDictionaryBase>& pages = json->beginArray("pages"); |
| + for (HeapPage<Header>* page = m_firstPage; page; page = page->next(), ++info->pageCount) { |
| + // FIXME: To limit the size of the snapshot we only output "threshold" many page snapshots. |
| + TracedArray<TracedArray<TracedDictionaryBase> >* jsonPage = 0; |
| + if (info->pageCount < GC_PROFILE_HEAP_PAGE_DUMP_THRESHOLD) { |
| + jsonPage = &pages.beginArray(); |
| + jsonPage->pushInteger(reinterpret_cast<intptr_t>(page)); |
| + } |
| + page->snapshot(jsonPage, info); |
| + if (jsonPage) |
| + jsonPage->endArray(); |
| + } |
| + pages.endArray(); |
| + |
| + TracedArray<TracedDictionaryBase>& largeObjects = json->beginArray("largeObjects"); |
| + for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; current = current->next()) { |
| + TracedDictionary<TracedArray<TracedDictionaryBase> >& jsonCurrent = largeObjects.beginDictionary(); |
| + current->snapshot(&jsonCurrent, info); |
| + jsonCurrent.endDictionary(); |
| + } |
| + largeObjects.endArray(); |
| + |
| + size_t pagePoolSize = 0; |
| + for (PagePoolEntry* page = m_pagePool; page; page = page->next()) |
| + ++pagePoolSize; |
| + |
| + json->setInteger("pagePoolSize", pagePoolSize) |
| + .setInteger("pageCount", info->pageCount - previousPageCount); |
| +} |
| +#endif |
| + |
| template<typename Header> |
| void ThreadHeap<Header>::addToFreeList(Address address, size_t size) |
| { |
| @@ -1201,7 +1241,7 @@ void HeapPage<Header>::checkAndMarkPointer(Visitor* visitor, Address address) |
| if (!header) |
| return; |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| visitor->setHostInfo(&address, "stack"); |
| #endif |
| if (hasVTable(header) && !vTableInitialized(header->payload())) |
| @@ -1210,7 +1250,7 @@ void HeapPage<Header>::checkAndMarkPointer(Visitor* visitor, Address address) |
| visitor->mark(header, traceCallback(header)); |
| } |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| template<typename Header> |
| const GCInfo* HeapPage<Header>::findGCInfo(Address address) |
| { |
| @@ -1228,6 +1268,42 @@ const GCInfo* HeapPage<Header>::findGCInfo(Address address) |
| } |
| #endif |
| +#if GC_PROFILE_HEAP |
| +template<typename Header> |
| +void HeapPage<Header>::snapshot(TracedArrayBase* json, ThreadState::SnapshotInfo* info) |
| +{ |
| + Header* header = 0; |
| + for (Address addr = payload(); addr < end(); addr += header->size()) { |
| + header = reinterpret_cast<Header*>(addr); |
| + if (json) |
| + json->pushInteger(header->encodedSize()); |
| + if (header->isFree()) { |
| + info->freeSize += header->size(); |
| + continue; |
| + } |
| + |
| + size_t tag = info->getClassTag(header->gcInfo()); |
| + size_t age = header->age(); |
| + if (json) |
| + json->pushInteger(tag); |
| + if (header->isMarked()) { |
| + info->liveCount[tag] += 1; |
| + info->liveSize += header->size(); |
| + // Count objects that are live when promoted to the final generation. |
| + if (age == maxHeapObjectAge - 1) |
| + info->generations[tag][maxHeapObjectAge] += 1; |
| + header->incAge(); |
|
haraken
2014/07/14 02:26:14
Do we want to increase the age when age == maxHeap
zerny-chromium
2014/07/28 11:54:41
No, the increment check against maxHeapObjectAge i
zerny-chromium
2014/07/28 11:57:59
(Too quick there) We do want to increment when it
|
| + } else { |
| + info->deadCount[tag] += 1; |
| + info->deadSize += header->size(); |
| + // Count objects that are dead before the final generation. |
| + if (age < maxHeapObjectAge) |
| + info->generations[tag][age] += 1; |
| + } |
| + } |
| +} |
| +#endif |
| + |
| #if defined(ADDRESS_SANITIZER) |
| template<typename Header> |
| void HeapPage<Header>::poisonUnmarkedObjects() |
| @@ -1289,6 +1365,37 @@ void LargeHeapObject<Header>::getStats(HeapStats& stats) |
| stats.increaseObjectSpace(payloadSize()); |
| } |
| +#if GC_PROFILE_HEAP |
| +template<typename Header> |
| +void LargeHeapObject<Header>::snapshot(TracedDictionaryBase* json, ThreadState::SnapshotInfo* info) |
| +{ |
| + Header* header = heapObjectHeader(); |
| + size_t tag = info->getClassTag(header->gcInfo()); |
| + size_t age = header->age(); |
| + if (isMarked()) { |
| + info->liveCount[tag] += 1; |
| + info->liveSize += header->size(); |
| + // Count objects that are live when promoted to the final generation. |
| + if (age == maxHeapObjectAge - 1) |
| + info->generations[tag][maxHeapObjectAge] += 1; |
| + header->incAge(); |
|
haraken
2014/07/14 02:26:14
Do we want to increase the age when age == maxHeap
zerny-chromium
2014/07/28 11:54:41
Ditto.
|
| + } else { |
| + info->deadCount[tag] += 1; |
| + info->deadSize += header->size(); |
| + // Count objects that are live when promoted to the final generation. |
| + if (age == maxHeapObjectAge - 1) |
| + info->generations[tag][maxHeapObjectAge] += 1; |
| + header->incAge(); |
|
haraken
2014/07/14 02:26:14
Factor out the line 1378 - 1381 and the line 1385
zerny-chromium
2014/07/28 11:54:41
This is a copy-paste error. The dead-branch should
|
| + } |
| + |
| + if (json) { |
| + json->setInteger("class", tag) |
| + .setInteger("size", header->size()) |
| + .setInteger("isMarked", isMarked()); |
| + } |
| +} |
| +#endif |
| + |
| template<typename Entry> |
| void HeapExtentCache<Entry>::flush() |
| { |
| @@ -1403,7 +1510,7 @@ bool CallbackStack::popAndInvokeCallback(CallbackStack** first, Visitor* visitor |
| Item* item = --m_current; |
| VisitorCallback callback = item->callback(); |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| if (ThreadState::isAnyThreadInGC()) // weak-processing will also use popAndInvokeCallback |
| visitor->setHostInfo(item->object(), classOf(item->object())); |
| #endif |
| @@ -1461,7 +1568,7 @@ bool CallbackStack::hasCallbackForObject(const void* object) |
| class MarkingVisitor : public Visitor { |
| public: |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| typedef HashSet<uintptr_t> LiveObjectSet; |
| typedef HashMap<String, LiveObjectSet> LiveObjectMap; |
| typedef HashMap<uintptr_t, std::pair<uintptr_t, String> > ObjectGraph; |
| @@ -1474,7 +1581,7 @@ public: |
| if (header->isMarked()) |
| return; |
| header->mark(); |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| MutexLocker locker(objectGraphMutex()); |
| String className(classOf(objectPointer)); |
| { |
| @@ -1580,7 +1687,7 @@ public: |
| FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS) |
| #undef DEFINE_VISITOR_METHODS |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| void reportStats() |
| { |
| fprintf(stderr, "\n---------- AFTER MARKING -------------------\n"); |
| @@ -1758,12 +1865,14 @@ Address Heap::checkAndMarkPointer(Visitor* visitor, Address address) |
| return 0; |
| } |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| const GCInfo* Heap::findGCInfo(Address address) |
| { |
| return ThreadState::findGCInfoFromAllThreads(address); |
| } |
| +#endif |
| +#if GC_PROFILE_MARKING |
| void Heap::dumpPathToObjectOnNextGC(void* p) |
| { |
| static_cast<MarkingVisitor*>(s_markingVisitor)->dumpPathToObjectOnNextGC(p); |
| @@ -1880,10 +1989,10 @@ void Heap::collectGarbage(ThreadState::StackState stackState) |
| ScriptForbiddenScope forbiddenScope; |
| s_lastGCWasConservative = false; |
| - TRACE_EVENT0("blink", "Heap::collectGarbage"); |
| - TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "BlinkGC"); |
| + TRACE_EVENT0(GC_PROFILE_GROUP, "Heap::collectGarbage"); |
| + TRACE_EVENT_SCOPED_SAMPLING_STATE(GC_PROFILE_GROUP, "BlinkGC"); |
| double timeStamp = WTF::currentTimeMS(); |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| static_cast<MarkingVisitor*>(s_markingVisitor)->objectGraph().clear(); |
| #endif |
| @@ -1920,7 +2029,7 @@ void Heap::collectGarbage(ThreadState::StackState stackState) |
| // callback phase, so the marking stack should still be empty here. |
| ASSERT(s_markingStack->isEmpty()); |
| -#if ENABLE(GC_TRACING) |
| +#if GC_PROFILE_MARKING |
| static_cast<MarkingVisitor*>(s_markingVisitor)->reportStats(); |
| #endif |