| Index: Source/platform/heap/ThreadState.cpp
 | 
| diff --git a/Source/platform/heap/ThreadState.cpp b/Source/platform/heap/ThreadState.cpp
 | 
| index 1d63ae03a8e385f9488fde3945a09f569e285277..8d48c23acdc8d33f2ad7d57b84f64e0d4312eec3 100644
 | 
| --- a/Source/platform/heap/ThreadState.cpp
 | 
| +++ b/Source/platform/heap/ThreadState.cpp
 | 
| @@ -38,6 +38,9 @@
 | 
|  #include "platform/heap/Heap.h"
 | 
|  #include "public/platform/Platform.h"
 | 
|  #include "wtf/ThreadingPrimitives.h"
 | 
| +#if ENABLE(GC_PROFILE_HEAP)
 | 
| +#include "platform/TracedValue.h"
 | 
| +#endif
 | 
|  
 | 
|  #if OS(WIN)
 | 
|  #include <stddef.h>
 | 
| @@ -568,7 +571,7 @@ bool ThreadState::checkAndMarkPointer(Visitor* visitor, Address address)
 | 
|      return false;
 | 
|  }
 | 
|  
 | 
| -#if ENABLE(GC_TRACING)
 | 
| +#if ENABLE(GC_PROFILE_MARKING)
 | 
|  const GCInfo* ThreadState::findGCInfo(Address address)
 | 
|  {
 | 
|      BaseHeapPage* page = heapPageFromAddress(address);
 | 
| @@ -579,6 +582,66 @@ const GCInfo* ThreadState::findGCInfo(Address address)
 | 
|  }
 | 
|  #endif
 | 
|  
 | 
| +#if ENABLE(GC_PROFILE_HEAP)
 | 
| +size_t ThreadState::SnapshotInfo::getClassTag(const GCInfo* gcinfo)
 | 
| +{
 | 
| +    HashMap<const GCInfo*, size_t>::AddResult result = classTags.add(gcinfo, classTags.size());
 | 
| +    if (result.isNewEntry) {
 | 
| +        liveCount.append(0);
 | 
| +        deadCount.append(0);
 | 
| +        generations.append(Vector<int, 8>());
 | 
| +        generations.last().fill(0, 8);
 | 
| +    }
 | 
| +    return result.storedValue->value;
 | 
| +}
 | 
| +
 | 
| +void ThreadState::snapshot()
 | 
| +{
 | 
| +    SnapshotInfo info(this);
 | 
| +    RefPtr<TracedValue> json = TracedValue::create();
 | 
| +
 | 
| +#define SNAPSHOT_HEAP(HeapType)                                         \
 | 
| +    {                                                                   \
 | 
| +        json->beginDictionary();                                        \
 | 
| +        json->setString("name", #HeapType);                             \
 | 
| +        m_heaps[HeapType##Heap]->snapshot(json.get(), &info);          \
 | 
| +        json->endDictionary();                                          \
 | 
| +    }
 | 
| +    json->beginArray("heaps");
 | 
| +    SNAPSHOT_HEAP(General);
 | 
| +    FOR_EACH_TYPED_HEAP(SNAPSHOT_HEAP);
 | 
| +    json->endArray();
 | 
| +#undef SNAPSHOT_HEAP
 | 
| +
 | 
| +    json->setInteger("allocatedSpace", m_stats.totalAllocatedSpace());
 | 
| +    json->setInteger("objectSpace", m_stats.totalObjectSpace());
 | 
| +    json->setInteger("liveSize", info.liveSize);
 | 
| +    json->setInteger("deadSize", info.deadSize);
 | 
| +    json->setInteger("freeSize", info.freeSize);
 | 
| +    json->setInteger("pageCount", info.freeSize);
 | 
| +
 | 
| +    Vector<String> classNameVector(info.classTags.size());
 | 
| +    for (HashMap<const GCInfo*, size_t>::iterator it = info.classTags.begin(); it != info.classTags.end(); ++it)
 | 
| +        classNameVector[it->value] = it->key->m_className;
 | 
| +
 | 
| +    json->beginArray("classes");
 | 
| +    for (size_t i = 0; i < classNameVector.size(); ++i) {
 | 
| +        json->beginDictionary();
 | 
| +        json->setString("name", classNameVector[i]);
 | 
| +        json->setInteger("liveCount", info.liveCount[i]);
 | 
| +        json->setInteger("deadCount", info.deadCount[i]);
 | 
| +        json->beginArray("generations");
 | 
| +        for (size_t j = 0; j < heapObjectGenerations; ++j)
 | 
| +            json->pushInteger(info.generations[i][j]);
 | 
| +        json->endArray();
 | 
| +        json->endDictionary();
 | 
| +    }
 | 
| +    json->endArray();
 | 
| +
 | 
| +    TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID("blink_gc", "ThreadState", this, json);
 | 
| +}
 | 
| +#endif
 | 
| +
 | 
|  void ThreadState::pushWeakObjectPointerCallback(void* object, WeakPointerCallback callback)
 | 
|  {
 | 
|      CallbackStack::Item* slot = m_weakCallbackStack->allocateEntry(&m_weakCallbackStack);
 | 
| @@ -886,7 +949,17 @@ void ThreadState::performPendingSweep()
 | 
|      if (!sweepRequested())
 | 
|          return;
 | 
|  
 | 
| -    TRACE_EVENT0("blink", "ThreadState::performPendingSweep");
 | 
| +#if ENABLE(GC_PROFILE_HEAP)
 | 
| +    // We snapshot the heap prior to sweeping to get numbers for both resources
 | 
| +    // that have been allocated since the last GC and for resources that are
 | 
| +    // going to be freed.
 | 
| +    bool gcTracingEnabled;
 | 
| +    TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink_gc", &gcTracingEnabled);
 | 
| +    if (gcTracingEnabled && m_stats.totalObjectSpace() > 0)
 | 
| +        snapshot();
 | 
| +#endif
 | 
| +
 | 
| +    TRACE_EVENT0("blink_gc", "ThreadState::performPendingSweep");
 | 
|  
 | 
|      double timeStamp = WTF::currentTimeMS();
 | 
|      const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE();
 | 
| @@ -961,7 +1034,7 @@ ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads()
 | 
|      return threads;
 | 
|  }
 | 
|  
 | 
| -#if ENABLE(GC_TRACING)
 | 
| +#if ENABLE(GC_PROFILE_MARKING)
 | 
|  const GCInfo* ThreadState::findGCInfoFromAllThreads(Address address)
 | 
|  {
 | 
|      bool needLockForIteration = !isAnyThreadInGC();
 | 
| @@ -981,4 +1054,5 @@ const GCInfo* ThreadState::findGCInfoFromAllThreads(Address address)
 | 
|      return 0;
 | 
|  }
 | 
|  #endif
 | 
| +
 | 
|  }
 | 
| 
 |