| Index: src/heap.cc
|
| diff --git a/src/heap.cc b/src/heap.cc
|
| index 949dd80c3b9a28e1eed25ca1db1a95ae657ddf91..01dc1e78982963025b6c826c5aff03b319e335d5 100644
|
| --- a/src/heap.cc
|
| +++ b/src/heap.cc
|
| @@ -33,6 +33,7 @@
|
| #include "codegen-inl.h"
|
| #include "compilation-cache.h"
|
| #include "debug.h"
|
| +#include "heap-profiler.h"
|
| #include "global-handles.h"
|
| #include "mark-compact.h"
|
| #include "natives.h"
|
| @@ -3544,164 +3545,6 @@ void HeapIterator::reset() {
|
| }
|
|
|
|
|
| -#ifdef ENABLE_LOGGING_AND_PROFILING
|
| -namespace {
|
| -
|
| -// JSConstructorProfile is responsible for gathering and logging
|
| -// "constructor profile" of JS object allocated on heap.
|
| -// It is run during garbage collection cycle, thus it doesn't need
|
| -// to use handles.
|
| -class JSConstructorProfile BASE_EMBEDDED {
|
| - public:
|
| - JSConstructorProfile() : zscope_(DELETE_ON_EXIT) {}
|
| - void CollectStats(HeapObject* obj);
|
| - void PrintStats();
|
| - // Used by ZoneSplayTree::ForEach.
|
| - void Call(String* name, const NumberAndSizeInfo& number_and_size);
|
| - private:
|
| - struct TreeConfig {
|
| - typedef String* Key;
|
| - typedef NumberAndSizeInfo Value;
|
| - static const Key kNoKey;
|
| - static const Value kNoValue;
|
| - // Strings are unique, so it is sufficient to compare their pointers.
|
| - static int Compare(const Key& a, const Key& b) {
|
| - return a == b ? 0 : (a < b ? -1 : 1);
|
| - }
|
| - };
|
| -
|
| - typedef ZoneSplayTree<TreeConfig> JSObjectsInfoTree;
|
| - static int CalculateJSObjectNetworkSize(JSObject* obj);
|
| -
|
| - ZoneScope zscope_;
|
| - JSObjectsInfoTree js_objects_info_tree_;
|
| -};
|
| -
|
| -const JSConstructorProfile::TreeConfig::Key
|
| - JSConstructorProfile::TreeConfig::kNoKey = NULL;
|
| -const JSConstructorProfile::TreeConfig::Value
|
| - JSConstructorProfile::TreeConfig::kNoValue;
|
| -
|
| -
|
| -int JSConstructorProfile::CalculateJSObjectNetworkSize(JSObject* obj) {
|
| - int size = obj->Size();
|
| - // If 'properties' and 'elements' are non-empty (thus, non-shared),
|
| - // take their size into account.
|
| - if (FixedArray::cast(obj->properties())->length() != 0) {
|
| - size += obj->properties()->Size();
|
| - }
|
| - if (FixedArray::cast(obj->elements())->length() != 0) {
|
| - size += obj->elements()->Size();
|
| - }
|
| - return size;
|
| -}
|
| -
|
| -
|
| -void JSConstructorProfile::Call(String* name,
|
| - const NumberAndSizeInfo& number_and_size) {
|
| - ASSERT(name != NULL);
|
| - SmartPointer<char> s_name(
|
| - name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
|
| - LOG(HeapSampleJSConstructorEvent(*s_name,
|
| - number_and_size.number(),
|
| - number_and_size.bytes()));
|
| -}
|
| -
|
| -
|
| -void JSConstructorProfile::CollectStats(HeapObject* obj) {
|
| - String* constructor = NULL;
|
| - int size;
|
| - if (obj->IsString()) {
|
| - constructor = Heap::String_symbol();
|
| - size = obj->Size();
|
| - } else if (obj->IsJSObject()) {
|
| - JSObject* js_obj = JSObject::cast(obj);
|
| - constructor = js_obj->constructor_name();
|
| - size = CalculateJSObjectNetworkSize(js_obj);
|
| - } else {
|
| - return;
|
| - }
|
| -
|
| - JSObjectsInfoTree::Locator loc;
|
| - if (!js_objects_info_tree_.Find(constructor, &loc)) {
|
| - js_objects_info_tree_.Insert(constructor, &loc);
|
| - }
|
| - NumberAndSizeInfo number_and_size = loc.value();
|
| - number_and_size.increment_number(1);
|
| - number_and_size.increment_bytes(size);
|
| - loc.set_value(number_and_size);
|
| -}
|
| -
|
| -
|
| -void JSConstructorProfile::PrintStats() {
|
| - js_objects_info_tree_.ForEach(this);
|
| -}
|
| -
|
| -} // namespace
|
| -#endif
|
| -
|
| -
|
| -//
|
| -// HeapProfiler class implementation.
|
| -//
|
| -#ifdef ENABLE_LOGGING_AND_PROFILING
|
| -void HeapProfiler::CollectStats(HeapObject* obj, HistogramInfo* info) {
|
| - InstanceType type = obj->map()->instance_type();
|
| - ASSERT(0 <= type && type <= LAST_TYPE);
|
| - info[type].increment_number(1);
|
| - info[type].increment_bytes(obj->Size());
|
| -}
|
| -#endif
|
| -
|
| -
|
| -#ifdef ENABLE_LOGGING_AND_PROFILING
|
| -void HeapProfiler::WriteSample() {
|
| - LOG(HeapSampleBeginEvent("Heap", "allocated"));
|
| - LOG(HeapSampleStats(
|
| - "Heap", "allocated", Heap::Capacity(), Heap::SizeOfObjects()));
|
| -
|
| - HistogramInfo info[LAST_TYPE+1];
|
| -#define DEF_TYPE_NAME(name) info[name].set_name(#name);
|
| - INSTANCE_TYPE_LIST(DEF_TYPE_NAME)
|
| -#undef DEF_TYPE_NAME
|
| -
|
| - JSConstructorProfile js_cons_profile;
|
| - HeapIterator iterator;
|
| - while (iterator.has_next()) {
|
| - HeapObject* obj = iterator.next();
|
| - CollectStats(obj, info);
|
| - js_cons_profile.CollectStats(obj);
|
| - }
|
| -
|
| - // Lump all the string types together.
|
| - int string_number = 0;
|
| - int string_bytes = 0;
|
| -#define INCREMENT_SIZE(type, size, name, camel_name) \
|
| - string_number += info[type].number(); \
|
| - string_bytes += info[type].bytes();
|
| - STRING_TYPE_LIST(INCREMENT_SIZE)
|
| -#undef INCREMENT_SIZE
|
| - if (string_bytes > 0) {
|
| - LOG(HeapSampleItemEvent("STRING_TYPE", string_number, string_bytes));
|
| - }
|
| -
|
| - for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) {
|
| - if (info[i].bytes() > 0) {
|
| - LOG(HeapSampleItemEvent(info[i].name(), info[i].number(),
|
| - info[i].bytes()));
|
| - }
|
| - }
|
| -
|
| - js_cons_profile.PrintStats();
|
| -
|
| - LOG(HeapSampleEndEvent("Heap", "allocated"));
|
| -}
|
| -
|
| -
|
| -#endif
|
| -
|
| -
|
| -
|
| #ifdef DEBUG
|
|
|
| static bool search_for_any_global;
|
|
|