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 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
313 struct NodesPair { | 313 struct NodesPair { |
314 NodesPair(ProfileNode* src, ProfileNode* dst) | 314 NodesPair(ProfileNode* src, ProfileNode* dst) |
315 : src(src), dst(dst) { } | 315 : src(src), dst(dst) { } |
316 ProfileNode* src; | 316 ProfileNode* src; |
317 ProfileNode* dst; | 317 ProfileNode* dst; |
318 }; | 318 }; |
319 | 319 |
320 | 320 |
321 class FilteredCloneCallback { | 321 class FilteredCloneCallback { |
322 public: | 322 public: |
323 explicit FilteredCloneCallback(ProfileNode* dst_root, int security_token_id) | 323 FilteredCloneCallback(ProfileNode* dst_root, int security_token_id) |
324 : stack_(10), | 324 : stack_(10), |
325 security_token_id_(security_token_id) { | 325 security_token_id_(security_token_id) { |
326 stack_.Add(NodesPair(NULL, dst_root)); | 326 stack_.Add(NodesPair(NULL, dst_root)); |
327 } | 327 } |
328 | 328 |
329 void BeforeTraversingChild(ProfileNode* parent, ProfileNode* child) { | 329 void BeforeTraversingChild(ProfileNode* parent, ProfileNode* child) { |
330 if (IsTokenAcceptable(child->entry()->security_token_id(), | 330 if (IsTokenAcceptable(child->entry()->security_token_id(), |
331 parent->entry()->security_token_id())) { | 331 parent->entry()->security_token_id())) { |
332 ProfileNode* clone = stack_.last().dst->FindOrAddChild(child->entry()); | 332 ProfileNode* clone = stack_.last().dst->FindOrAddChild(child->entry()); |
333 clone->IncreaseSelfTicks(child->self_ticks()); | 333 clone->IncreaseSelfTicks(child->self_ticks()); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
543 | 543 |
544 static void DeleteCodeEntry(CodeEntry** entry_ptr) { | 544 static void DeleteCodeEntry(CodeEntry** entry_ptr) { |
545 delete *entry_ptr; | 545 delete *entry_ptr; |
546 } | 546 } |
547 | 547 |
548 static void DeleteCpuProfile(CpuProfile** profile_ptr) { | 548 static void DeleteCpuProfile(CpuProfile** profile_ptr) { |
549 delete *profile_ptr; | 549 delete *profile_ptr; |
550 } | 550 } |
551 | 551 |
552 static void DeleteProfilesList(List<CpuProfile*>** list_ptr) { | 552 static void DeleteProfilesList(List<CpuProfile*>** list_ptr) { |
553 (*list_ptr)->Iterate(DeleteCpuProfile); | 553 if (*list_ptr) { |
Vitaly Repeshko
2011/03/22 14:30:36
nit: Use explicit != NULL comparison.
mnaganov (inactive)
2011/03/22 16:03:09
Done.
| |
554 delete *list_ptr; | 554 (*list_ptr)->Iterate(DeleteCpuProfile); |
555 delete *list_ptr; | |
556 } | |
555 } | 557 } |
556 | 558 |
557 CpuProfilesCollection::~CpuProfilesCollection() { | 559 CpuProfilesCollection::~CpuProfilesCollection() { |
558 delete current_profiles_semaphore_; | 560 delete current_profiles_semaphore_; |
559 current_profiles_.Iterate(DeleteCpuProfile); | 561 current_profiles_.Iterate(DeleteCpuProfile); |
562 detached_profiles_.Iterate(DeleteCpuProfile); | |
560 profiles_by_token_.Iterate(DeleteProfilesList); | 563 profiles_by_token_.Iterate(DeleteProfilesList); |
561 code_entries_.Iterate(DeleteCodeEntry); | 564 code_entries_.Iterate(DeleteCodeEntry); |
562 } | 565 } |
563 | 566 |
564 | 567 |
565 bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid) { | 568 bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid) { |
566 ASSERT(uid > 0); | 569 ASSERT(uid > 0); |
567 current_profiles_semaphore_->Wait(); | 570 current_profiles_semaphore_->Wait(); |
568 if (current_profiles_.length() >= kMaxSimultaneousProfiles) { | 571 if (current_profiles_.length() >= kMaxSimultaneousProfiles) { |
569 current_profiles_semaphore_->Signal(); | 572 current_profiles_semaphore_->Signal(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
614 ASSERT(entry->value == NULL); | 617 ASSERT(entry->value == NULL); |
615 entry->value = reinterpret_cast<void*>(unabridged_list->length() - 1); | 618 entry->value = reinterpret_cast<void*>(unabridged_list->length() - 1); |
616 return GetProfile(security_token_id, profile->uid()); | 619 return GetProfile(security_token_id, profile->uid()); |
617 } | 620 } |
618 return NULL; | 621 return NULL; |
619 } | 622 } |
620 | 623 |
621 | 624 |
622 CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id, | 625 CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id, |
623 unsigned uid) { | 626 unsigned uid) { |
624 HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid), | 627 int index = GetProfileIndex(uid); |
625 static_cast<uint32_t>(uid), | 628 if (index < 0) return NULL; |
626 false); | |
627 int index; | |
628 if (entry != NULL) { | |
629 index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | |
630 } else { | |
631 return NULL; | |
632 } | |
633 List<CpuProfile*>* unabridged_list = | 629 List<CpuProfile*>* unabridged_list = |
634 profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)]; | 630 profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)]; |
635 if (security_token_id == TokenEnumerator::kNoSecurityToken) { | 631 if (security_token_id == TokenEnumerator::kNoSecurityToken) { |
636 return unabridged_list->at(index); | 632 return unabridged_list->at(index); |
637 } | 633 } |
638 List<CpuProfile*>* list = GetProfilesList(security_token_id); | 634 List<CpuProfile*>* list = GetProfilesList(security_token_id); |
639 if (list->at(index) == NULL) { | 635 if (list->at(index) == NULL) { |
640 (*list)[index] = | 636 (*list)[index] = |
641 unabridged_list->at(index)->FilteredClone(security_token_id); | 637 unabridged_list->at(index)->FilteredClone(security_token_id); |
642 } | 638 } |
643 return list->at(index); | 639 return list->at(index); |
644 } | 640 } |
645 | 641 |
646 | 642 |
643 int CpuProfilesCollection::GetProfileIndex(unsigned uid) { | |
644 HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid), | |
645 static_cast<uint32_t>(uid), | |
646 false); | |
647 return entry != NULL ? | |
648 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)) : -1; | |
649 } | |
650 | |
651 | |
647 bool CpuProfilesCollection::IsLastProfile(const char* title) { | 652 bool CpuProfilesCollection::IsLastProfile(const char* title) { |
648 // Called from VM thread, and only it can mutate the list, | 653 // Called from VM thread, and only it can mutate the list, |
649 // so no locking is needed here. | 654 // so no locking is needed here. |
650 if (current_profiles_.length() != 1) return false; | 655 if (current_profiles_.length() != 1) return false; |
651 return StrLength(title) == 0 | 656 return StrLength(title) == 0 |
652 || strcmp(current_profiles_[0]->title(), title) == 0; | 657 || strcmp(current_profiles_[0]->title(), title) == 0; |
653 } | 658 } |
654 | 659 |
655 | 660 |
661 void CpuProfilesCollection::RemoveProfile(CpuProfile* profile) { | |
662 // Called from VM thread for a completed profile. | |
663 unsigned uid = profile->uid(); | |
664 int index = GetProfileIndex(uid); | |
665 if (index < 0) { | |
666 detached_profiles_.RemoveElement(profile); | |
667 return; | |
668 } | |
669 profiles_uids_.Remove(reinterpret_cast<void*>(uid), | |
670 static_cast<uint32_t>(uid)); | |
671 // Decrement all indexes above the deleted one. | |
672 for (HashMap::Entry* p = profiles_uids_.Start(); | |
673 p; | |
Vitaly Repeshko
2011/03/22 14:30:36
!= NULL
mnaganov (inactive)
2011/03/22 16:03:09
Done.
| |
674 p = profiles_uids_.Next(p)) { | |
675 intptr_t p_index = reinterpret_cast<intptr_t>(p->value); | |
676 if (p_index > index) { | |
677 p->value = reinterpret_cast<void*>(p_index - 1); | |
678 } | |
679 } | |
680 for (int i = 0; i < profiles_by_token_.length(); ++i) { | |
681 List<CpuProfile*>* list = profiles_by_token_[i]; | |
682 if (list != NULL && index < list->length()) { | |
683 // Move all filtered clones into detached_profiles_, | |
684 // so we can know that they are still in use. | |
685 CpuProfile* cloned_profile = list->Remove(index); | |
686 if (cloned_profile != NULL && cloned_profile != profile) { | |
687 detached_profiles_.Add(cloned_profile); | |
688 } | |
689 } | |
690 } | |
691 } | |
692 | |
693 | |
656 int CpuProfilesCollection::TokenToIndex(int security_token_id) { | 694 int CpuProfilesCollection::TokenToIndex(int security_token_id) { |
657 ASSERT(TokenEnumerator::kNoSecurityToken == -1); | 695 ASSERT(TokenEnumerator::kNoSecurityToken == -1); |
658 return security_token_id + 1; // kNoSecurityToken -> 0, 0 -> 1, ... | 696 return security_token_id + 1; // kNoSecurityToken -> 0, 0 -> 1, ... |
659 } | 697 } |
660 | 698 |
661 | 699 |
662 List<CpuProfile*>* CpuProfilesCollection::GetProfilesList( | 700 List<CpuProfile*>* CpuProfilesCollection::GetProfilesList( |
663 int security_token_id) { | 701 int security_token_id) { |
664 const int index = TokenToIndex(security_token_id); | 702 const int index = TokenToIndex(security_token_id); |
665 const int lists_to_add = index - profiles_by_token_.length() + 1; | 703 const int lists_to_add = index - profiles_by_token_.length() + 1; |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1261 p != NULL; | 1299 p != NULL; |
1262 p = retaining_paths_.Next(p)) { | 1300 p = retaining_paths_.Next(p)) { |
1263 List<HeapGraphPath*>* list = | 1301 List<HeapGraphPath*>* list = |
1264 reinterpret_cast<List<HeapGraphPath*>*>(p->value); | 1302 reinterpret_cast<List<HeapGraphPath*>*>(p->value); |
1265 list->Iterate(DeleteHeapGraphPath); | 1303 list->Iterate(DeleteHeapGraphPath); |
1266 delete list; | 1304 delete list; |
1267 } | 1305 } |
1268 } | 1306 } |
1269 | 1307 |
1270 | 1308 |
1309 void HeapSnapshot::Delete() { | |
1310 collection_->RemoveSnapshot(this); | |
1311 delete this; | |
1312 } | |
1313 | |
1314 | |
1271 void HeapSnapshot::AllocateEntries(int entries_count, | 1315 void HeapSnapshot::AllocateEntries(int entries_count, |
1272 int children_count, | 1316 int children_count, |
1273 int retainers_count) { | 1317 int retainers_count) { |
1274 ASSERT(raw_entries_ == NULL); | 1318 ASSERT(raw_entries_ == NULL); |
1275 raw_entries_ = NewArray<char>( | 1319 raw_entries_ = NewArray<char>( |
1276 HeapEntry::EntriesSize(entries_count, children_count, retainers_count)); | 1320 HeapEntry::EntriesSize(entries_count, children_count, retainers_count)); |
1277 #ifdef DEBUG | 1321 #ifdef DEBUG |
1278 raw_entries_size_ = | 1322 raw_entries_size_ = |
1279 HeapEntry::EntriesSize(entries_count, children_count, retainers_count); | 1323 HeapEntry::EntriesSize(entries_count, children_count, retainers_count); |
1280 #endif | 1324 #endif |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1572 | 1616 |
1573 | 1617 |
1574 HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) { | 1618 HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) { |
1575 HashMap::Entry* entry = snapshots_uids_.Lookup(reinterpret_cast<void*>(uid), | 1619 HashMap::Entry* entry = snapshots_uids_.Lookup(reinterpret_cast<void*>(uid), |
1576 static_cast<uint32_t>(uid), | 1620 static_cast<uint32_t>(uid), |
1577 false); | 1621 false); |
1578 return entry != NULL ? reinterpret_cast<HeapSnapshot*>(entry->value) : NULL; | 1622 return entry != NULL ? reinterpret_cast<HeapSnapshot*>(entry->value) : NULL; |
1579 } | 1623 } |
1580 | 1624 |
1581 | 1625 |
1626 void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) { | |
1627 snapshots_.RemoveElement(snapshot); | |
1628 unsigned uid = snapshot->uid(); | |
1629 snapshots_uids_.Remove(reinterpret_cast<void*>(uid), | |
1630 static_cast<uint32_t>(uid)); | |
1631 } | |
1632 | |
1633 | |
1582 HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots( | 1634 HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots( |
1583 HeapSnapshot* snapshot1, | 1635 HeapSnapshot* snapshot1, |
1584 HeapSnapshot* snapshot2) { | 1636 HeapSnapshot* snapshot2) { |
1585 return comparator_.Compare(snapshot1, snapshot2); | 1637 return comparator_.Compare(snapshot1, snapshot2); |
1586 } | 1638 } |
1587 | 1639 |
1588 | 1640 |
1589 HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder = | 1641 HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder = |
1590 reinterpret_cast<HeapEntry*>(1); | 1642 reinterpret_cast<HeapEntry*>(1); |
1591 | 1643 |
(...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3196 | 3248 |
3197 | 3249 |
3198 String* GetConstructorNameForHeapProfile(JSObject* object) { | 3250 String* GetConstructorNameForHeapProfile(JSObject* object) { |
3199 if (object->IsJSFunction()) return HEAP->closure_symbol(); | 3251 if (object->IsJSFunction()) return HEAP->closure_symbol(); |
3200 return object->constructor_name(); | 3252 return object->constructor_name(); |
3201 } | 3253 } |
3202 | 3254 |
3203 } } // namespace v8::internal | 3255 } } // namespace v8::internal |
3204 | 3256 |
3205 #endif // ENABLE_LOGGING_AND_PROFILING | 3257 #endif // ENABLE_LOGGING_AND_PROFILING |
OLD | NEW |