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

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

Issue 148503002: A64: Synchronize with r15545. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 12 matching lines...) Expand all
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "profile-generator-inl.h" 30 #include "profile-generator-inl.h"
31 31
32 #include "compiler.h" 32 #include "compiler.h"
33 #include "debug.h"
34 #include "sampler.h"
33 #include "global-handles.h" 35 #include "global-handles.h"
34 #include "scopeinfo.h" 36 #include "scopeinfo.h"
35 #include "unicode.h" 37 #include "unicode.h"
36 #include "zone-inl.h" 38 #include "zone-inl.h"
37 #include "debug.h"
38 39
39 namespace v8 { 40 namespace v8 {
40 namespace internal { 41 namespace internal {
41 42
42 43
43 TokenEnumerator::TokenEnumerator()
44 : token_locations_(4),
45 token_removed_(4) {
46 }
47
48
49 TokenEnumerator::~TokenEnumerator() {
50 Isolate* isolate = Isolate::Current();
51 for (int i = 0; i < token_locations_.length(); ++i) {
52 if (!token_removed_[i]) {
53 isolate->global_handles()->ClearWeakness(token_locations_[i]);
54 isolate->global_handles()->Destroy(token_locations_[i]);
55 }
56 }
57 }
58
59
60 int TokenEnumerator::GetTokenId(Object* token) {
61 Isolate* isolate = Isolate::Current();
62 if (token == NULL) return TokenEnumerator::kNoSecurityToken;
63 for (int i = 0; i < token_locations_.length(); ++i) {
64 if (*token_locations_[i] == token && !token_removed_[i]) return i;
65 }
66 Handle<Object> handle = isolate->global_handles()->Create(token);
67 // handle.location() points to a memory cell holding a pointer
68 // to a token object in the V8's heap.
69 isolate->global_handles()->MakeWeak(handle.location(),
70 this,
71 TokenRemovedCallback);
72 token_locations_.Add(handle.location());
73 token_removed_.Add(false);
74 return token_locations_.length() - 1;
75 }
76
77
78 void TokenEnumerator::TokenRemovedCallback(v8::Isolate* isolate,
79 v8::Persistent<v8::Value>* handle,
80 void* parameter) {
81 reinterpret_cast<TokenEnumerator*>(parameter)->TokenRemoved(
82 Utils::OpenPersistent(handle).location());
83 handle->Dispose(isolate);
84 }
85
86
87 void TokenEnumerator::TokenRemoved(Object** token_location) {
88 for (int i = 0; i < token_locations_.length(); ++i) {
89 if (token_locations_[i] == token_location && !token_removed_[i]) {
90 token_removed_[i] = true;
91 return;
92 }
93 }
94 }
95
96
97 StringsStorage::StringsStorage() 44 StringsStorage::StringsStorage()
98 : names_(StringsMatch) { 45 : names_(StringsMatch) {
99 } 46 }
100 47
101 48
102 StringsStorage::~StringsStorage() { 49 StringsStorage::~StringsStorage() {
103 for (HashMap::Entry* p = names_.Start(); 50 for (HashMap::Entry* p = names_.Start();
104 p != NULL; 51 p != NULL;
105 p = names_.Next(p)) { 52 p = names_.Next(p)) {
106 DeleteArray(reinterpret_cast<const char*>(p->value)); 53 DeleteArray(reinterpret_cast<const char*>(p->value));
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 || (tag_ == entry->tag_ 175 || (tag_ == entry->tag_
229 && shared_id_ == entry->shared_id_ 176 && shared_id_ == entry->shared_id_
230 && (shared_id_ != 0 177 && (shared_id_ != 0
231 || (name_prefix_ == entry->name_prefix_ 178 || (name_prefix_ == entry->name_prefix_
232 && name_ == entry->name_ 179 && name_ == entry->name_
233 && resource_name_ == entry->resource_name_ 180 && resource_name_ == entry->resource_name_
234 && line_number_ == entry->line_number_))); 181 && line_number_ == entry->line_number_)));
235 } 182 }
236 183
237 184
185 void CodeEntry::SetBuiltinId(Builtins::Name id) {
186 tag_ = Logger::BUILTIN_TAG;
187 builtin_id_ = id;
188 }
189
190
238 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { 191 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
239 HashMap::Entry* map_entry = 192 HashMap::Entry* map_entry =
240 children_.Lookup(entry, CodeEntryHash(entry), false); 193 children_.Lookup(entry, CodeEntryHash(entry), false);
241 return map_entry != NULL ? 194 return map_entry != NULL ?
242 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL; 195 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL;
243 } 196 }
244 197
245 198
246 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { 199 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) {
247 HashMap::Entry* map_entry = 200 HashMap::Entry* map_entry =
(...skipping 12 matching lines...) Expand all
260 return tree_->TicksToMillis(self_ticks_); 213 return tree_->TicksToMillis(self_ticks_);
261 } 214 }
262 215
263 216
264 double ProfileNode::GetTotalMillis() const { 217 double ProfileNode::GetTotalMillis() const {
265 return tree_->TicksToMillis(total_ticks_); 218 return tree_->TicksToMillis(total_ticks_);
266 } 219 }
267 220
268 221
269 void ProfileNode::Print(int indent) { 222 void ProfileNode::Print(int indent) {
270 OS::Print("%5u %5u %*c %s%s [%d] #%d", 223 OS::Print("%5u %5u %*c %s%s #%d %d",
271 total_ticks_, self_ticks_, 224 total_ticks_, self_ticks_,
272 indent, ' ', 225 indent, ' ',
273 entry_->name_prefix(), 226 entry_->name_prefix(),
274 entry_->name(), 227 entry_->name(),
275 entry_->security_token_id(), 228 entry_->script_id(),
276 id()); 229 id());
277 if (entry_->resource_name()[0] != '\0') 230 if (entry_->resource_name()[0] != '\0')
278 OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number()); 231 OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number());
279 OS::Print("\n"); 232 OS::Print("\n");
280 for (HashMap::Entry* p = children_.Start(); 233 for (HashMap::Entry* p = children_.Start();
281 p != NULL; 234 p != NULL;
282 p = children_.Next(p)) { 235 p = children_.Next(p)) {
283 reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2); 236 reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2);
284 } 237 }
285 } 238 }
286 239
287 240
288 class DeleteNodesCallback { 241 class DeleteNodesCallback {
289 public: 242 public:
290 void BeforeTraversingChild(ProfileNode*, ProfileNode*) { } 243 void BeforeTraversingChild(ProfileNode*, ProfileNode*) { }
291 244
292 void AfterAllChildrenTraversed(ProfileNode* node) { 245 void AfterAllChildrenTraversed(ProfileNode* node) {
293 delete node; 246 delete node;
294 } 247 }
295 248
296 void AfterChildTraversed(ProfileNode*, ProfileNode*) { } 249 void AfterChildTraversed(ProfileNode*, ProfileNode*) { }
297 }; 250 };
298 251
299 252
300 ProfileTree::ProfileTree() 253 ProfileTree::ProfileTree()
301 : root_entry_(Logger::FUNCTION_TAG, "", "(root)"), 254 : root_entry_(Logger::FUNCTION_TAG, "(root)"),
302 next_node_id_(1), 255 next_node_id_(1),
303 root_(new ProfileNode(this, &root_entry_)) { 256 root_(new ProfileNode(this, &root_entry_)) {
304 } 257 }
305 258
306 259
307 ProfileTree::~ProfileTree() { 260 ProfileTree::~ProfileTree() {
308 DeleteNodesCallback cb; 261 DeleteNodesCallback cb;
309 TraverseDepthFirst(&cb); 262 TraverseDepthFirst(&cb);
310 } 263 }
311 264
(...skipping 26 matching lines...) Expand all
338 291
339 292
340 struct NodesPair { 293 struct NodesPair {
341 NodesPair(ProfileNode* src, ProfileNode* dst) 294 NodesPair(ProfileNode* src, ProfileNode* dst)
342 : src(src), dst(dst) { } 295 : src(src), dst(dst) { }
343 ProfileNode* src; 296 ProfileNode* src;
344 ProfileNode* dst; 297 ProfileNode* dst;
345 }; 298 };
346 299
347 300
348 class FilteredCloneCallback {
349 public:
350 FilteredCloneCallback(ProfileNode* dst_root, int security_token_id)
351 : stack_(10),
352 security_token_id_(security_token_id) {
353 stack_.Add(NodesPair(NULL, dst_root));
354 }
355
356 void BeforeTraversingChild(ProfileNode* parent, ProfileNode* child) {
357 if (IsTokenAcceptable(child->entry()->security_token_id(),
358 parent->entry()->security_token_id())) {
359 ProfileNode* clone = stack_.last().dst->FindOrAddChild(child->entry());
360 clone->IncreaseSelfTicks(child->self_ticks());
361 stack_.Add(NodesPair(child, clone));
362 } else {
363 // Attribute ticks to parent node.
364 stack_.last().dst->IncreaseSelfTicks(child->self_ticks());
365 }
366 }
367
368 void AfterAllChildrenTraversed(ProfileNode* parent) { }
369
370 void AfterChildTraversed(ProfileNode*, ProfileNode* child) {
371 if (stack_.last().src == child) {
372 stack_.RemoveLast();
373 }
374 }
375
376 private:
377 bool IsTokenAcceptable(int token, int parent_token) {
378 if (token == TokenEnumerator::kNoSecurityToken
379 || token == security_token_id_) return true;
380 if (token == TokenEnumerator::kInheritsSecurityToken) {
381 ASSERT(parent_token != TokenEnumerator::kInheritsSecurityToken);
382 return parent_token == TokenEnumerator::kNoSecurityToken
383 || parent_token == security_token_id_;
384 }
385 return false;
386 }
387
388 List<NodesPair> stack_;
389 int security_token_id_;
390 };
391
392 void ProfileTree::FilteredClone(ProfileTree* src, int security_token_id) {
393 ms_to_ticks_scale_ = src->ms_to_ticks_scale_;
394 FilteredCloneCallback cb(root_, security_token_id);
395 src->TraverseDepthFirst(&cb);
396 CalculateTotalTicks();
397 }
398
399
400 void ProfileTree::SetTickRatePerMs(double ticks_per_ms) { 301 void ProfileTree::SetTickRatePerMs(double ticks_per_ms) {
401 ms_to_ticks_scale_ = ticks_per_ms > 0 ? 1.0 / ticks_per_ms : 1.0; 302 ms_to_ticks_scale_ = ticks_per_ms > 0 ? 1.0 / ticks_per_ms : 1.0;
402 } 303 }
403 304
404 305
405 class Position { 306 class Position {
406 public: 307 public:
407 explicit Position(ProfileNode* node) 308 explicit Position(ProfileNode* node)
408 : node(node), child_idx_(0) { } 309 : node(node), child_idx_(0) { }
409 INLINE(ProfileNode* current_child()) { 310 INLINE(ProfileNode* current_child()) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 void CpuProfile::CalculateTotalTicks() { 381 void CpuProfile::CalculateTotalTicks() {
481 top_down_.CalculateTotalTicks(); 382 top_down_.CalculateTotalTicks();
482 } 383 }
483 384
484 385
485 void CpuProfile::SetActualSamplingRate(double actual_sampling_rate) { 386 void CpuProfile::SetActualSamplingRate(double actual_sampling_rate) {
486 top_down_.SetTickRatePerMs(actual_sampling_rate); 387 top_down_.SetTickRatePerMs(actual_sampling_rate);
487 } 388 }
488 389
489 390
490 CpuProfile* CpuProfile::FilteredClone(int security_token_id) {
491 ASSERT(security_token_id != TokenEnumerator::kNoSecurityToken);
492 CpuProfile* clone = new CpuProfile(title_, uid_, false);
493 clone->top_down_.FilteredClone(&top_down_, security_token_id);
494 return clone;
495 }
496
497
498 void CpuProfile::ShortPrint() { 391 void CpuProfile::ShortPrint() {
499 OS::Print("top down "); 392 OS::Print("top down ");
500 top_down_.ShortPrint(); 393 top_down_.ShortPrint();
501 } 394 }
502 395
503 396
504 void CpuProfile::Print() { 397 void CpuProfile::Print() {
505 OS::Print("[Top down]:\n"); 398 OS::Print("[Top down]:\n");
506 top_down_.Print(); 399 top_down_.Print();
507 } 400 }
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 } 479 }
587 480
588 481
589 void CodeMap::Print() { 482 void CodeMap::Print() {
590 CodeTreePrinter printer; 483 CodeTreePrinter printer;
591 tree_.ForEach(&printer); 484 tree_.ForEach(&printer);
592 } 485 }
593 486
594 487
595 CpuProfilesCollection::CpuProfilesCollection() 488 CpuProfilesCollection::CpuProfilesCollection()
596 : profiles_uids_(UidsMatch), 489 : current_profiles_semaphore_(OS::CreateSemaphore(1)) {
597 current_profiles_semaphore_(OS::CreateSemaphore(1)) {
598 // Create list of unabridged profiles.
599 profiles_by_token_.Add(new List<CpuProfile*>());
600 } 490 }
601 491
602 492
603 static void DeleteCodeEntry(CodeEntry** entry_ptr) { 493 static void DeleteCodeEntry(CodeEntry** entry_ptr) {
604 delete *entry_ptr; 494 delete *entry_ptr;
605 } 495 }
606 496
497
607 static void DeleteCpuProfile(CpuProfile** profile_ptr) { 498 static void DeleteCpuProfile(CpuProfile** profile_ptr) {
608 delete *profile_ptr; 499 delete *profile_ptr;
609 } 500 }
610 501
611 static void DeleteProfilesList(List<CpuProfile*>** list_ptr) {
612 if (*list_ptr != NULL) {
613 (*list_ptr)->Iterate(DeleteCpuProfile);
614 delete *list_ptr;
615 }
616 }
617 502
618 CpuProfilesCollection::~CpuProfilesCollection() { 503 CpuProfilesCollection::~CpuProfilesCollection() {
619 delete current_profiles_semaphore_; 504 delete current_profiles_semaphore_;
505 finished_profiles_.Iterate(DeleteCpuProfile);
620 current_profiles_.Iterate(DeleteCpuProfile); 506 current_profiles_.Iterate(DeleteCpuProfile);
621 detached_profiles_.Iterate(DeleteCpuProfile);
622 profiles_by_token_.Iterate(DeleteProfilesList);
623 code_entries_.Iterate(DeleteCodeEntry); 507 code_entries_.Iterate(DeleteCodeEntry);
624 } 508 }
625 509
626 510
627 bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid, 511 bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid,
628 bool record_samples) { 512 bool record_samples) {
629 ASSERT(uid > 0); 513 ASSERT(uid > 0);
630 current_profiles_semaphore_->Wait(); 514 current_profiles_semaphore_->Wait();
631 if (current_profiles_.length() >= kMaxSimultaneousProfiles) { 515 if (current_profiles_.length() >= kMaxSimultaneousProfiles) {
632 current_profiles_semaphore_->Signal(); 516 current_profiles_semaphore_->Signal();
633 return false; 517 return false;
634 } 518 }
635 for (int i = 0; i < current_profiles_.length(); ++i) { 519 for (int i = 0; i < current_profiles_.length(); ++i) {
636 if (strcmp(current_profiles_[i]->title(), title) == 0) { 520 if (strcmp(current_profiles_[i]->title(), title) == 0) {
637 // Ignore attempts to start profile with the same title. 521 // Ignore attempts to start profile with the same title.
638 current_profiles_semaphore_->Signal(); 522 current_profiles_semaphore_->Signal();
639 return false; 523 return false;
640 } 524 }
641 } 525 }
642 current_profiles_.Add(new CpuProfile(title, uid, record_samples)); 526 current_profiles_.Add(new CpuProfile(title, uid, record_samples));
643 current_profiles_semaphore_->Signal(); 527 current_profiles_semaphore_->Signal();
644 return true; 528 return true;
645 } 529 }
646 530
647 531
648 CpuProfile* CpuProfilesCollection::StopProfiling(int security_token_id, 532 CpuProfile* CpuProfilesCollection::StopProfiling(const char* title,
649 const char* title,
650 double actual_sampling_rate) { 533 double actual_sampling_rate) {
651 const int title_len = StrLength(title); 534 const int title_len = StrLength(title);
652 CpuProfile* profile = NULL; 535 CpuProfile* profile = NULL;
653 current_profiles_semaphore_->Wait(); 536 current_profiles_semaphore_->Wait();
654 for (int i = current_profiles_.length() - 1; i >= 0; --i) { 537 for (int i = current_profiles_.length() - 1; i >= 0; --i) {
655 if (title_len == 0 || strcmp(current_profiles_[i]->title(), title) == 0) { 538 if (title_len == 0 || strcmp(current_profiles_[i]->title(), title) == 0) {
656 profile = current_profiles_.Remove(i); 539 profile = current_profiles_.Remove(i);
657 break; 540 break;
658 } 541 }
659 } 542 }
660 current_profiles_semaphore_->Signal(); 543 current_profiles_semaphore_->Signal();
661 544
662 if (profile != NULL) { 545 if (profile == NULL) return NULL;
663 profile->CalculateTotalTicks(); 546 profile->CalculateTotalTicks();
664 profile->SetActualSamplingRate(actual_sampling_rate); 547 profile->SetActualSamplingRate(actual_sampling_rate);
665 List<CpuProfile*>* unabridged_list = 548 finished_profiles_.Add(profile);
666 profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)]; 549 return profile;
667 unabridged_list->Add(profile);
668 HashMap::Entry* entry =
669 profiles_uids_.Lookup(reinterpret_cast<void*>(profile->uid()),
670 static_cast<uint32_t>(profile->uid()),
671 true);
672 ASSERT(entry->value == NULL);
673 entry->value = reinterpret_cast<void*>(unabridged_list->length() - 1);
674 return GetProfile(security_token_id, profile->uid());
675 }
676 return NULL;
677 } 550 }
678 551
679 552
680 CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id,
681 unsigned uid) {
682 int index = GetProfileIndex(uid);
683 if (index < 0) return NULL;
684 List<CpuProfile*>* unabridged_list =
685 profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
686 if (security_token_id == TokenEnumerator::kNoSecurityToken) {
687 return unabridged_list->at(index);
688 }
689 List<CpuProfile*>* list = GetProfilesList(security_token_id);
690 if (list->at(index) == NULL) {
691 (*list)[index] =
692 unabridged_list->at(index)->FilteredClone(security_token_id);
693 }
694 return list->at(index);
695 }
696
697
698 int CpuProfilesCollection::GetProfileIndex(unsigned uid) {
699 HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid),
700 static_cast<uint32_t>(uid),
701 false);
702 return entry != NULL ?
703 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)) : -1;
704 }
705
706
707 bool CpuProfilesCollection::IsLastProfile(const char* title) { 553 bool CpuProfilesCollection::IsLastProfile(const char* title) {
708 // Called from VM thread, and only it can mutate the list, 554 // Called from VM thread, and only it can mutate the list,
709 // so no locking is needed here. 555 // so no locking is needed here.
710 if (current_profiles_.length() != 1) return false; 556 if (current_profiles_.length() != 1) return false;
711 return StrLength(title) == 0 557 return StrLength(title) == 0
712 || strcmp(current_profiles_[0]->title(), title) == 0; 558 || strcmp(current_profiles_[0]->title(), title) == 0;
713 } 559 }
714 560
715 561
716 void CpuProfilesCollection::RemoveProfile(CpuProfile* profile) { 562 void CpuProfilesCollection::RemoveProfile(CpuProfile* profile) {
717 // Called from VM thread for a completed profile. 563 // Called from VM thread for a completed profile.
718 unsigned uid = profile->uid(); 564 unsigned uid = profile->uid();
719 int index = GetProfileIndex(uid); 565 for (int i = 0; i < finished_profiles_.length(); i++) {
720 if (index < 0) { 566 if (uid == finished_profiles_[i]->uid()) {
721 detached_profiles_.RemoveElement(profile); 567 finished_profiles_.Remove(i);
722 return; 568 return;
723 }
724 profiles_uids_.Remove(reinterpret_cast<void*>(uid),
725 static_cast<uint32_t>(uid));
726 // Decrement all indexes above the deleted one.
727 for (HashMap::Entry* p = profiles_uids_.Start();
728 p != NULL;
729 p = profiles_uids_.Next(p)) {
730 intptr_t p_index = reinterpret_cast<intptr_t>(p->value);
731 if (p_index > index) {
732 p->value = reinterpret_cast<void*>(p_index - 1);
733 } 569 }
734 } 570 }
735 for (int i = 0; i < profiles_by_token_.length(); ++i) { 571 UNREACHABLE();
736 List<CpuProfile*>* list = profiles_by_token_[i];
737 if (list != NULL && index < list->length()) {
738 // Move all filtered clones into detached_profiles_,
739 // so we can know that they are still in use.
740 CpuProfile* cloned_profile = list->Remove(index);
741 if (cloned_profile != NULL && cloned_profile != profile) {
742 detached_profiles_.Add(cloned_profile);
743 }
744 }
745 }
746 } 572 }
747 573
748 574
749 int CpuProfilesCollection::TokenToIndex(int security_token_id) {
750 ASSERT(TokenEnumerator::kNoSecurityToken == -1);
751 return security_token_id + 1; // kNoSecurityToken -> 0, 0 -> 1, ...
752 }
753
754
755 List<CpuProfile*>* CpuProfilesCollection::GetProfilesList(
756 int security_token_id) {
757 const int index = TokenToIndex(security_token_id);
758 const int lists_to_add = index - profiles_by_token_.length() + 1;
759 if (lists_to_add > 0) profiles_by_token_.AddBlock(NULL, lists_to_add);
760 List<CpuProfile*>* unabridged_list =
761 profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
762 const int current_count = unabridged_list->length();
763 if (profiles_by_token_[index] == NULL) {
764 profiles_by_token_[index] = new List<CpuProfile*>(current_count);
765 }
766 List<CpuProfile*>* list = profiles_by_token_[index];
767 const int profiles_to_add = current_count - list->length();
768 if (profiles_to_add > 0) list->AddBlock(NULL, profiles_to_add);
769 return list;
770 }
771
772
773 List<CpuProfile*>* CpuProfilesCollection::Profiles(int security_token_id) {
774 List<CpuProfile*>* unabridged_list =
775 profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
776 if (security_token_id == TokenEnumerator::kNoSecurityToken) {
777 return unabridged_list;
778 }
779 List<CpuProfile*>* list = GetProfilesList(security_token_id);
780 const int current_count = unabridged_list->length();
781 for (int i = 0; i < current_count; ++i) {
782 if (list->at(i) == NULL) {
783 (*list)[i] = unabridged_list->at(i)->FilteredClone(security_token_id);
784 }
785 }
786 return list;
787 }
788
789
790 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
791 Name* name,
792 String* resource_name,
793 int line_number) {
794 CodeEntry* entry = new CodeEntry(tag,
795 CodeEntry::kEmptyNamePrefix,
796 GetFunctionName(name),
797 TokenEnumerator::kNoSecurityToken,
798 GetName(resource_name),
799 line_number);
800 code_entries_.Add(entry);
801 return entry;
802 }
803
804
805 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
806 const char* name) {
807 CodeEntry* entry = new CodeEntry(tag,
808 CodeEntry::kEmptyNamePrefix,
809 GetFunctionName(name));
810 code_entries_.Add(entry);
811 return entry;
812 }
813
814
815 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
816 const char* name_prefix,
817 Name* name) {
818 CodeEntry* entry = new CodeEntry(tag,
819 name_prefix,
820 GetName(name),
821 TokenEnumerator::kInheritsSecurityToken);
822 code_entries_.Add(entry);
823 return entry;
824 }
825
826
827 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
828 int args_count) {
829 CodeEntry* entry = new CodeEntry(tag,
830 "args_count: ",
831 GetName(args_count),
832 TokenEnumerator::kInheritsSecurityToken);
833 code_entries_.Add(entry);
834 return entry;
835 }
836
837
838 void CpuProfilesCollection::AddPathToCurrentProfiles( 575 void CpuProfilesCollection::AddPathToCurrentProfiles(
839 const Vector<CodeEntry*>& path) { 576 const Vector<CodeEntry*>& path) {
840 // As starting / stopping profiles is rare relatively to this 577 // As starting / stopping profiles is rare relatively to this
841 // method, we don't bother minimizing the duration of lock holding, 578 // method, we don't bother minimizing the duration of lock holding,
842 // e.g. copying contents of the list to a local vector. 579 // e.g. copying contents of the list to a local vector.
843 current_profiles_semaphore_->Wait(); 580 current_profiles_semaphore_->Wait();
844 for (int i = 0; i < current_profiles_.length(); ++i) { 581 for (int i = 0; i < current_profiles_.length(); ++i) {
845 current_profiles_[i]->AddPath(path); 582 current_profiles_[i]->AddPath(path);
846 } 583 }
847 current_profiles_semaphore_->Signal(); 584 current_profiles_semaphore_->Signal();
848 } 585 }
849 586
850 587
588 CodeEntry* CpuProfilesCollection::NewCodeEntry(
589 Logger::LogEventsAndTags tag,
590 const char* name,
591 const char* name_prefix,
592 const char* resource_name,
593 int line_number) {
594 CodeEntry* code_entry = new CodeEntry(tag,
595 name,
596 name_prefix,
597 resource_name,
598 line_number);
599 code_entries_.Add(code_entry);
600 return code_entry;
601 }
602
603
851 void SampleRateCalculator::Tick() { 604 void SampleRateCalculator::Tick() {
852 if (--wall_time_query_countdown_ == 0) 605 if (--wall_time_query_countdown_ == 0)
853 UpdateMeasurements(OS::TimeCurrentMillis()); 606 UpdateMeasurements(OS::TimeCurrentMillis());
854 } 607 }
855 608
856 609
857 void SampleRateCalculator::UpdateMeasurements(double current_time) { 610 void SampleRateCalculator::UpdateMeasurements(double current_time) {
858 if (measurements_count_++ != 0) { 611 if (measurements_count_++ != 0) {
859 const double measured_ticks_per_ms = 612 const double measured_ticks_per_ms =
860 (kWallTimeQueryIntervalMs * ticks_per_ms_) / 613 (kWallTimeQueryIntervalMs * ticks_per_ms_) /
861 (current_time - last_wall_time_); 614 (current_time - last_wall_time_);
862 // Update the average value. 615 // Update the average value.
863 ticks_per_ms_ += 616 ticks_per_ms_ +=
864 (measured_ticks_per_ms - ticks_per_ms_) / measurements_count_; 617 (measured_ticks_per_ms - ticks_per_ms_) / measurements_count_;
865 // Update the externally accessible result. 618 // Update the externally accessible result.
866 result_ = static_cast<AtomicWord>(ticks_per_ms_ * kResultScale); 619 result_ = static_cast<AtomicWord>(ticks_per_ms_ * kResultScale);
867 } 620 }
868 last_wall_time_ = current_time; 621 last_wall_time_ = current_time;
869 wall_time_query_countdown_ = 622 wall_time_query_countdown_ =
870 static_cast<unsigned>(kWallTimeQueryIntervalMs * ticks_per_ms_); 623 static_cast<unsigned>(kWallTimeQueryIntervalMs * ticks_per_ms_);
871 } 624 }
872 625
873 626
874 const char* const ProfileGenerator::kAnonymousFunctionName = 627 const char* const ProfileGenerator::kAnonymousFunctionName =
875 "(anonymous function)"; 628 "(anonymous function)";
876 const char* const ProfileGenerator::kProgramEntryName = 629 const char* const ProfileGenerator::kProgramEntryName =
877 "(program)"; 630 "(program)";
878 const char* const ProfileGenerator::kGarbageCollectorEntryName = 631 const char* const ProfileGenerator::kGarbageCollectorEntryName =
879 "(garbage collector)"; 632 "(garbage collector)";
633 const char* const ProfileGenerator::kUnresolvedFunctionName =
634 "(unresolved function)";
880 635
881 636
882 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles) 637 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
883 : profiles_(profiles), 638 : profiles_(profiles),
884 program_entry_( 639 program_entry_(
885 profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)), 640 profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)),
886 gc_entry_( 641 gc_entry_(
887 profiles->NewCodeEntry(Logger::BUILTIN_TAG, 642 profiles->NewCodeEntry(Logger::BUILTIN_TAG,
888 kGarbageCollectorEntryName)) { 643 kGarbageCollectorEntryName)),
644 unresolved_entry_(
645 profiles->NewCodeEntry(Logger::FUNCTION_TAG,
646 kUnresolvedFunctionName)) {
889 } 647 }
890 648
891 649
892 void ProfileGenerator::RecordTickSample(const TickSample& sample) { 650 void ProfileGenerator::RecordTickSample(const TickSample& sample) {
893 // Allocate space for stack frames + pc + function + vm-state. 651 // Allocate space for stack frames + pc + function + vm-state.
894 ScopedVector<CodeEntry*> entries(sample.frames_count + 3); 652 ScopedVector<CodeEntry*> entries(sample.frames_count + 3);
895 // As actual number of decoded code entries may vary, initialize 653 // As actual number of decoded code entries may vary, initialize
896 // entries vector with NULL values. 654 // entries vector with NULL values.
897 CodeEntry** entry = entries.start(); 655 CodeEntry** entry = entries.start();
898 memset(entry, 0, entries.length() * sizeof(*entry)); 656 memset(entry, 0, entries.length() * sizeof(*entry));
899 if (sample.pc != NULL) { 657 if (sample.pc != NULL) {
900 Address start; 658 if (sample.has_external_callback) {
901 CodeEntry* pc_entry = code_map_.FindEntry(sample.pc, &start); 659 // Don't use PC when in external callback code, as it can point
902 // If pc is in the function code before it set up stack frame or after the 660 // inside callback's code, and we will erroneously report
903 // frame was destroyed SafeStackFrameIterator incorrectly thinks that 661 // that a callback calls itself.
904 // ebp contains return address of the current function and skips caller's 662 *entry++ = code_map_.FindEntry(sample.external_callback);
905 // frame. Check for this case and just skip such samples. 663 } else {
906 if (pc_entry) { 664 Address start;
907 List<OffsetRange>* ranges = pc_entry->no_frame_ranges(); 665 CodeEntry* pc_entry = code_map_.FindEntry(sample.pc, &start);
908 if (ranges) { 666 // If pc is in the function code before it set up stack frame or after the
909 Code* code = Code::cast(HeapObject::FromAddress(start)); 667 // frame was destroyed SafeStackFrameIterator incorrectly thinks that
910 int pc_offset = static_cast<int>(sample.pc - code->instruction_start()); 668 // ebp contains return address of the current function and skips caller's
911 for (int i = 0; i < ranges->length(); i++) { 669 // frame. Check for this case and just skip such samples.
912 OffsetRange& range = ranges->at(i); 670 if (pc_entry) {
913 if (range.from <= pc_offset && pc_offset < range.to) { 671 List<OffsetRange>* ranges = pc_entry->no_frame_ranges();
914 return; 672 if (ranges) {
673 Code* code = Code::cast(HeapObject::FromAddress(start));
674 int pc_offset = static_cast<int>(
675 sample.pc - code->instruction_start());
676 for (int i = 0; i < ranges->length(); i++) {
677 OffsetRange& range = ranges->at(i);
678 if (range.from <= pc_offset && pc_offset < range.to) {
679 return;
680 }
681 }
682 }
683 *entry++ = pc_entry;
684
685 if (pc_entry->builtin_id() == Builtins::kFunctionCall ||
686 pc_entry->builtin_id() == Builtins::kFunctionApply) {
687 // When current function is FunctionCall or FunctionApply builtin the
688 // top frame is either frame of the calling JS function or internal
689 // frame. In the latter case we know the caller for sure but in the
690 // former case we don't so we simply replace the frame with
691 // 'unresolved' entry.
692 if (sample.top_frame_type == StackFrame::JAVA_SCRIPT) {
693 *entry++ = unresolved_entry_;
915 } 694 }
916 } 695 }
917 } 696 }
918 } 697 }
919 *entry++ = pc_entry;
920
921 if (sample.has_external_callback) {
922 // Don't use PC when in external callback code, as it can point
923 // inside callback's code, and we will erroneously report
924 // that a callback calls itself.
925 *(entries.start()) = NULL;
926 *entry++ = code_map_.FindEntry(sample.external_callback);
927 }
928 698
929 for (const Address* stack_pos = sample.stack, 699 for (const Address* stack_pos = sample.stack,
930 *stack_end = stack_pos + sample.frames_count; 700 *stack_end = stack_pos + sample.frames_count;
931 stack_pos != stack_end; 701 stack_pos != stack_end;
932 ++stack_pos) { 702 ++stack_pos) {
933 *entry++ = code_map_.FindEntry(*stack_pos); 703 *entry++ = code_map_.FindEntry(*stack_pos);
934 } 704 }
935 } 705 }
936 706
937 if (FLAG_prof_browser_mode) { 707 if (FLAG_prof_browser_mode) {
938 bool no_symbolized_entries = true; 708 bool no_symbolized_entries = true;
939 for (CodeEntry** e = entries.start(); e != entry; ++e) { 709 for (CodeEntry** e = entries.start(); e != entry; ++e) {
940 if (*e != NULL) { 710 if (*e != NULL) {
941 no_symbolized_entries = false; 711 no_symbolized_entries = false;
942 break; 712 break;
943 } 713 }
944 } 714 }
945 // If no frames were symbolized, put the VM state entry in. 715 // If no frames were symbolized, put the VM state entry in.
946 if (no_symbolized_entries) { 716 if (no_symbolized_entries) {
947 *entry++ = EntryForVMState(sample.state); 717 *entry++ = EntryForVMState(sample.state);
948 } 718 }
949 } 719 }
950 720
951 profiles_->AddPathToCurrentProfiles(entries); 721 profiles_->AddPathToCurrentProfiles(entries);
952 } 722 }
953 723
954 724
955 } } // namespace v8::internal 725 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698