Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(559)

Side by Side Diff: src/profile-generator.cc

Issue 3769007: New Heap profiler: add dumping HeapNumbers and InternalFields to snapshot. (Closed)
Patch Set: Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/profile-generator.h ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 } 87 }
88 } 88 }
89 } 89 }
90 90
91 91
92 StringsStorage::StringsStorage() 92 StringsStorage::StringsStorage()
93 : names_(StringsMatch) { 93 : names_(StringsMatch) {
94 } 94 }
95 95
96 96
97 static void DeleteIndexName(char** name_ptr) {
98 DeleteArray(*name_ptr);
99 }
100
101
97 StringsStorage::~StringsStorage() { 102 StringsStorage::~StringsStorage() {
98 for (HashMap::Entry* p = names_.Start(); 103 for (HashMap::Entry* p = names_.Start();
99 p != NULL; 104 p != NULL;
100 p = names_.Next(p)) { 105 p = names_.Next(p)) {
101 DeleteArray(reinterpret_cast<const char*>(p->value)); 106 DeleteArray(reinterpret_cast<const char*>(p->value));
102 } 107 }
108 index_names_.Iterate(DeleteIndexName);
103 } 109 }
104 110
105 111
106 const char* StringsStorage::GetName(String* name) { 112 const char* StringsStorage::GetName(String* name) {
107 if (name->IsString()) { 113 if (name->IsString()) {
108 char* c_name = 114 char* c_name =
109 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(); 115 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach();
110 HashMap::Entry* cache_entry = names_.Lookup(c_name, name->Hash(), true); 116 HashMap::Entry* cache_entry = names_.Lookup(c_name, name->Hash(), true);
111 if (cache_entry->value == NULL) { 117 if (cache_entry->value == NULL) {
112 // New entry added. 118 // New entry added.
113 cache_entry->value = c_name; 119 cache_entry->value = c_name;
114 } else { 120 } else {
115 DeleteArray(c_name); 121 DeleteArray(c_name);
116 } 122 }
117 return reinterpret_cast<const char*>(cache_entry->value); 123 return reinterpret_cast<const char*>(cache_entry->value);
118 } 124 }
119 return ""; 125 return "";
120 } 126 }
121 127
122 128
129 const char* StringsStorage::GetName(int index) {
130 ASSERT(index >= 0);
131 if (index_names_.length() <= index) {
132 index_names_.AddBlock(
133 NULL, index - index_names_.length() + 1);
134 }
135 if (index_names_[index] == NULL) {
136 const int kMaximumNameLength = 32;
137 char* name = NewArray<char>(kMaximumNameLength);
138 OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", index);
139 index_names_[index] = name;
140 }
141 return index_names_[index];
142 }
143
144
123 const char* CodeEntry::kEmptyNamePrefix = ""; 145 const char* CodeEntry::kEmptyNamePrefix = "";
124 146
125 147
126 void CodeEntry::CopyData(const CodeEntry& source) { 148 void CodeEntry::CopyData(const CodeEntry& source) {
127 tag_ = source.tag_; 149 tag_ = source.tag_;
128 name_prefix_ = source.name_prefix_; 150 name_prefix_ = source.name_prefix_;
129 name_ = source.name_; 151 name_ = source.name_;
130 resource_name_ = source.resource_name_; 152 resource_name_ = source.resource_name_;
131 line_number_ = source.line_number_; 153 line_number_ = source.line_number_;
132 } 154 }
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 500
479 501
480 CpuProfilesCollection::CpuProfilesCollection() 502 CpuProfilesCollection::CpuProfilesCollection()
481 : profiles_uids_(UidsMatch), 503 : profiles_uids_(UidsMatch),
482 current_profiles_semaphore_(OS::CreateSemaphore(1)) { 504 current_profiles_semaphore_(OS::CreateSemaphore(1)) {
483 // Create list of unabridged profiles. 505 // Create list of unabridged profiles.
484 profiles_by_token_.Add(new List<CpuProfile*>()); 506 profiles_by_token_.Add(new List<CpuProfile*>());
485 } 507 }
486 508
487 509
488 static void DeleteArgsCountName(char** name_ptr) {
489 DeleteArray(*name_ptr);
490 }
491
492
493 static void DeleteCodeEntry(CodeEntry** entry_ptr) { 510 static void DeleteCodeEntry(CodeEntry** entry_ptr) {
494 delete *entry_ptr; 511 delete *entry_ptr;
495 } 512 }
496 513
497 static void DeleteCpuProfile(CpuProfile** profile_ptr) { 514 static void DeleteCpuProfile(CpuProfile** profile_ptr) {
498 delete *profile_ptr; 515 delete *profile_ptr;
499 } 516 }
500 517
501 static void DeleteProfilesList(List<CpuProfile*>** list_ptr) { 518 static void DeleteProfilesList(List<CpuProfile*>** list_ptr) {
502 (*list_ptr)->Iterate(DeleteCpuProfile); 519 (*list_ptr)->Iterate(DeleteCpuProfile);
503 delete *list_ptr; 520 delete *list_ptr;
504 } 521 }
505 522
506 CpuProfilesCollection::~CpuProfilesCollection() { 523 CpuProfilesCollection::~CpuProfilesCollection() {
507 delete current_profiles_semaphore_; 524 delete current_profiles_semaphore_;
508 current_profiles_.Iterate(DeleteCpuProfile); 525 current_profiles_.Iterate(DeleteCpuProfile);
509 profiles_by_token_.Iterate(DeleteProfilesList); 526 profiles_by_token_.Iterate(DeleteProfilesList);
510 code_entries_.Iterate(DeleteCodeEntry); 527 code_entries_.Iterate(DeleteCodeEntry);
511 args_count_names_.Iterate(DeleteArgsCountName);
512 } 528 }
513 529
514 530
515 bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid) { 531 bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid) {
516 ASSERT(uid > 0); 532 ASSERT(uid > 0);
517 current_profiles_semaphore_->Wait(); 533 current_profiles_semaphore_->Wait();
518 if (current_profiles_.length() >= kMaxSimultaneousProfiles) { 534 if (current_profiles_.length() >= kMaxSimultaneousProfiles) {
519 current_profiles_semaphore_->Signal(); 535 current_profiles_semaphore_->Signal();
520 return false; 536 return false;
521 } 537 }
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 } 715 }
700 716
701 717
702 CodeEntry* CpuProfilesCollection::NewCodeEntry(int security_token_id) { 718 CodeEntry* CpuProfilesCollection::NewCodeEntry(int security_token_id) {
703 CodeEntry* entry = new CodeEntry(security_token_id); 719 CodeEntry* entry = new CodeEntry(security_token_id);
704 code_entries_.Add(entry); 720 code_entries_.Add(entry);
705 return entry; 721 return entry;
706 } 722 }
707 723
708 724
709 const char* CpuProfilesCollection::GetName(int args_count) {
710 ASSERT(args_count >= 0);
711 if (args_count_names_.length() <= args_count) {
712 args_count_names_.AddBlock(
713 NULL, args_count - args_count_names_.length() + 1);
714 }
715 if (args_count_names_[args_count] == NULL) {
716 const int kMaximumNameLength = 32;
717 char* name = NewArray<char>(kMaximumNameLength);
718 OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", args_count);
719 args_count_names_[args_count] = name;
720 }
721 return args_count_names_[args_count];
722 }
723
724
725 void CpuProfilesCollection::AddPathToCurrentProfiles( 725 void CpuProfilesCollection::AddPathToCurrentProfiles(
726 const Vector<CodeEntry*>& path) { 726 const Vector<CodeEntry*>& path) {
727 // As starting / stopping profiles is rare relatively to this 727 // As starting / stopping profiles is rare relatively to this
728 // method, we don't bother minimizing the duration of lock holding, 728 // method, we don't bother minimizing the duration of lock holding,
729 // e.g. copying contents of the list to a local vector. 729 // e.g. copying contents of the list to a local vector.
730 current_profiles_semaphore_->Wait(); 730 current_profiles_semaphore_->Wait();
731 for (int i = 0; i < current_profiles_.length(); ++i) { 731 for (int i = 0; i < current_profiles_.length(); ++i) {
732 current_profiles_[i]->AddPath(path); 732 current_profiles_[i]->AddPath(path);
733 } 733 }
734 current_profiles_semaphore_->Signal(); 734 current_profiles_semaphore_->Signal();
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
995 995
996 const char* HeapEntry::TypeAsString() { 996 const char* HeapEntry::TypeAsString() {
997 switch (type()) { 997 switch (type()) {
998 case kInternal: return "/internal/"; 998 case kInternal: return "/internal/";
999 case kObject: return "/object/"; 999 case kObject: return "/object/";
1000 case kClosure: return "/closure/"; 1000 case kClosure: return "/closure/";
1001 case kString: return "/string/"; 1001 case kString: return "/string/";
1002 case kCode: return "/code/"; 1002 case kCode: return "/code/";
1003 case kArray: return "/array/"; 1003 case kArray: return "/array/";
1004 case kRegExp: return "/regexp/"; 1004 case kRegExp: return "/regexp/";
1005 case kHeapNumber: return "/number/";
1005 default: return "???"; 1006 default: return "???";
1006 } 1007 }
1007 } 1008 }
1008 1009
1009 1010
1010 int HeapEntry::EntriesSize(int entries_count, 1011 int HeapEntry::EntriesSize(int entries_count,
1011 int children_count, 1012 int children_count,
1012 int retainers_count) { 1013 int retainers_count) {
1013 return sizeof(HeapEntry) * entries_count // NOLINT 1014 return sizeof(HeapEntry) * entries_count // NOLINT
1014 + sizeof(HeapGraphEdge) * children_count // NOLINT 1015 + sizeof(HeapGraphEdge) * children_count // NOLINT
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1332 script->name()->IsString() ? 1333 script->name()->IsString() ?
1333 collection_->GetName(String::cast(script->name())) : "", 1334 collection_->GetName(String::cast(script->name())) : "",
1334 children_count, 1335 children_count,
1335 retainers_count); 1336 retainers_count);
1336 } else if (object->IsFixedArray()) { 1337 } else if (object->IsFixedArray()) {
1337 return AddEntry(object, 1338 return AddEntry(object,
1338 HeapEntry::kArray, 1339 HeapEntry::kArray,
1339 "", 1340 "",
1340 children_count, 1341 children_count,
1341 retainers_count); 1342 retainers_count);
1343 } else if (object->IsHeapNumber()) {
1344 return AddEntry(object,
1345 HeapEntry::kHeapNumber,
1346 "number",
1347 children_count,
1348 retainers_count);
1342 } 1349 }
1343 // No interest in this object. 1350 // No interest in this object.
1344 return NULL; 1351 return NULL;
1345 } 1352 }
1346 1353
1347 1354
1348 bool HeapSnapshot::WillAddEntry(HeapObject* object) { 1355 bool HeapSnapshot::WillAddEntry(HeapObject* object) {
1349 return object == kInternalRootObject 1356 return object == kInternalRootObject
1350 || object->IsJSFunction() 1357 || object->IsJSFunction()
1351 || object->IsJSRegExp() 1358 || object->IsJSRegExp()
1352 || object->IsJSObject() 1359 || object->IsJSObject()
1353 || object->IsString() 1360 || object->IsString()
1354 || object->IsCode() 1361 || object->IsCode()
1355 || object->IsSharedFunctionInfo() 1362 || object->IsSharedFunctionInfo()
1356 || object->IsScript() 1363 || object->IsScript()
1357 || object->IsFixedArray(); 1364 || object->IsFixedArray()
1365 || object->IsHeapNumber();
1358 } 1366 }
1359 1367
1360 1368
1361 static void HeapEntryClearPaint(HeapEntry** entry_ptr) { 1369 static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
1362 (*entry_ptr)->clear_paint(); 1370 (*entry_ptr)->clear_paint();
1363 } 1371 }
1364 1372
1365 void HeapSnapshot::ClearPaint() { 1373 void HeapSnapshot::ClearPaint() {
1366 entries_.Iterate(HeapEntryClearPaint); 1374 entries_.Iterate(HeapEntryClearPaint);
1367 } 1375 }
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after
1904 } 1912 }
1905 1913
1906 HeapEntry* entry = GetEntry(obj); 1914 HeapEntry* entry = GetEntry(obj);
1907 if (entry == NULL) return; // No interest in this object. 1915 if (entry == NULL) return; // No interest in this object.
1908 1916
1909 if (obj->IsJSObject()) { 1917 if (obj->IsJSObject()) {
1910 JSObject* js_obj = JSObject::cast(obj); 1918 JSObject* js_obj = JSObject::cast(obj);
1911 ExtractClosureReferences(js_obj, entry); 1919 ExtractClosureReferences(js_obj, entry);
1912 ExtractPropertyReferences(js_obj, entry); 1920 ExtractPropertyReferences(js_obj, entry);
1913 ExtractElementReferences(js_obj, entry); 1921 ExtractElementReferences(js_obj, entry);
1922 ExtractInternalReferences(js_obj, entry);
1914 SetPropertyReference( 1923 SetPropertyReference(
1915 obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype()); 1924 obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype());
1916 if (obj->IsJSFunction()) { 1925 if (obj->IsJSFunction()) {
1917 JSFunction* js_fun = JSFunction::cast(obj); 1926 JSFunction* js_fun = JSFunction::cast(obj);
1918 if (js_fun->has_prototype()) { 1927 if (js_fun->has_prototype()) {
1919 SetPropertyReference( 1928 SetPropertyReference(
1920 obj, entry, Heap::prototype_symbol(), js_fun->prototype()); 1929 obj, entry, Heap::prototype_symbol(), js_fun->prototype());
1921 } 1930 }
1922 } 1931 }
1923 } else if (obj->IsString()) { 1932 } else if (obj->IsString()) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2012 if (dictionary->IsKey(k)) { 2021 if (dictionary->IsKey(k)) {
2013 ASSERT(k->IsNumber()); 2022 ASSERT(k->IsNumber());
2014 uint32_t index = static_cast<uint32_t>(k->Number()); 2023 uint32_t index = static_cast<uint32_t>(k->Number());
2015 SetElementReference(js_obj, entry, index, dictionary->ValueAt(i)); 2024 SetElementReference(js_obj, entry, index, dictionary->ValueAt(i));
2016 } 2025 }
2017 } 2026 }
2018 } 2027 }
2019 } 2028 }
2020 2029
2021 2030
2031 void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj,
2032 HeapEntry* entry) {
2033 int length = js_obj->GetInternalFieldCount();
2034 for (int i = 0; i < length; ++i) {
2035 Object* o = js_obj->GetInternalField(i);
2036 SetInternalReference(js_obj, entry, i, o);
2037 }
2038 }
2039
2040
2022 void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj, 2041 void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj,
2023 HeapEntry* parent_entry, 2042 HeapEntry* parent_entry,
2024 String* reference_name, 2043 String* reference_name,
2025 Object* child_obj) { 2044 Object* child_obj) {
2026 HeapEntry* child_entry = GetEntry(child_obj); 2045 HeapEntry* child_entry = GetEntry(child_obj);
2027 if (child_entry != NULL) { 2046 if (child_entry != NULL) {
2028 filler_->SetNamedReference(HeapGraphEdge::kContextVariable, 2047 filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
2029 parent_obj, 2048 parent_obj,
2030 parent_entry, 2049 parent_entry,
2031 collection_->GetName(reference_name), 2050 collection_->GetName(reference_name),
(...skipping 24 matching lines...) Expand all
2056 filler_->SetNamedReference(HeapGraphEdge::kInternal, 2075 filler_->SetNamedReference(HeapGraphEdge::kInternal,
2057 parent_obj, 2076 parent_obj,
2058 parent_entry, 2077 parent_entry,
2059 reference_name, 2078 reference_name,
2060 child_obj, 2079 child_obj,
2061 child_entry); 2080 child_entry);
2062 } 2081 }
2063 } 2082 }
2064 2083
2065 2084
2085 void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
2086 HeapEntry* parent_entry,
2087 int index,
2088 Object* child_obj) {
2089 HeapEntry* child_entry = GetEntry(child_obj);
2090 if (child_entry != NULL) {
2091 filler_->SetNamedReference(HeapGraphEdge::kInternal,
2092 parent_obj,
2093 parent_entry,
2094 collection_->GetName(index),
2095 child_obj,
2096 child_entry);
2097 }
2098 }
2099
2100
2066 void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj, 2101 void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
2067 HeapEntry* parent_entry, 2102 HeapEntry* parent_entry,
2068 String* reference_name, 2103 String* reference_name,
2069 Object* child_obj) { 2104 Object* child_obj) {
2070 HeapEntry* child_entry = GetEntry(child_obj); 2105 HeapEntry* child_entry = GetEntry(child_obj);
2071 if (child_entry != NULL) { 2106 if (child_entry != NULL) {
2072 HeapGraphEdge::Type type = reference_name->length() > 0 ? 2107 HeapGraphEdge::Type type = reference_name->length() > 0 ?
2073 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; 2108 HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
2074 filler_->SetNamedReference(type, 2109 filler_->SetNamedReference(type,
2075 parent_obj, 2110 parent_obj,
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
2361 "," JSON_S("children_count") 2396 "," JSON_S("children_count")
2362 "," JSON_S("children")) 2397 "," JSON_S("children"))
2363 "," JSON_S("types") ":" JSON_A( 2398 "," JSON_S("types") ":" JSON_A(
2364 JSON_A( 2399 JSON_A(
2365 JSON_S("internal") 2400 JSON_S("internal")
2366 "," JSON_S("array") 2401 "," JSON_S("array")
2367 "," JSON_S("string") 2402 "," JSON_S("string")
2368 "," JSON_S("object") 2403 "," JSON_S("object")
2369 "," JSON_S("code") 2404 "," JSON_S("code")
2370 "," JSON_S("closure") 2405 "," JSON_S("closure")
2371 "," JSON_S("regexp")) 2406 "," JSON_S("regexp")
2407 "," JSON_S("number"))
2372 "," JSON_S("string") 2408 "," JSON_S("string")
2373 "," JSON_S("number") 2409 "," JSON_S("number")
2374 "," JSON_S("number") 2410 "," JSON_S("number")
2375 "," JSON_S("number") 2411 "," JSON_S("number")
2376 "," JSON_O( 2412 "," JSON_O(
2377 JSON_S("fields") ":" JSON_A( 2413 JSON_S("fields") ":" JSON_A(
2378 JSON_S("type") 2414 JSON_S("type")
2379 "," JSON_S("name_or_index") 2415 "," JSON_S("name_or_index")
2380 "," JSON_S("to_node")) 2416 "," JSON_S("to_node"))
2381 "," JSON_S("types") ":" JSON_A( 2417 "," JSON_S("types") ":" JSON_A(
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
2512 void HeapSnapshotJSONSerializer::SortHashMap( 2548 void HeapSnapshotJSONSerializer::SortHashMap(
2513 HashMap* map, List<HashMap::Entry*>* sorted_entries) { 2549 HashMap* map, List<HashMap::Entry*>* sorted_entries) {
2514 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) 2550 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p))
2515 sorted_entries->Add(p); 2551 sorted_entries->Add(p);
2516 sorted_entries->Sort(SortUsingEntryValue); 2552 sorted_entries->Sort(SortUsingEntryValue);
2517 } 2553 }
2518 2554
2519 } } // namespace v8::internal 2555 } } // namespace v8::internal
2520 2556
2521 #endif // ENABLE_LOGGING_AND_PROFILING 2557 #endif // ENABLE_LOGGING_AND_PROFILING
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698