OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |