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

Side by Side Diff: runtime/vm/profiler_service.cc

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month 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 | « runtime/vm/profiler_service.h ('k') | runtime/vm/profiler_test.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 (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/profiler_service.h" 5 #include "vm/profiler_service.h"
6 6
7 #include "vm/growable_array.h" 7 #include "vm/growable_array.h"
8 #include "vm/hash_map.h" 8 #include "vm/hash_map.h"
9 #include "vm/log.h" 9 #include "vm/log.h"
10 #include "vm/native_symbol.h" 10 #include "vm/native_symbol.h"
(...skipping 11 matching lines...) Expand all
22 DECLARE_FLAG(bool, profile_vm); 22 DECLARE_FLAG(bool, profile_vm);
23 23
24 #ifndef PRODUCT 24 #ifndef PRODUCT
25 25
26 class DeoptimizedCodeSet : public ZoneAllocated { 26 class DeoptimizedCodeSet : public ZoneAllocated {
27 public: 27 public:
28 explicit DeoptimizedCodeSet(Isolate* isolate) 28 explicit DeoptimizedCodeSet(Isolate* isolate)
29 : previous_( 29 : previous_(
30 GrowableObjectArray::ZoneHandle(isolate->deoptimized_code_array())), 30 GrowableObjectArray::ZoneHandle(isolate->deoptimized_code_array())),
31 current_(GrowableObjectArray::ZoneHandle( 31 current_(GrowableObjectArray::ZoneHandle(
32 previous_.IsNull() ? GrowableObjectArray::null() : 32 previous_.IsNull() ? GrowableObjectArray::null()
33 GrowableObjectArray::New())) { 33 : GrowableObjectArray::New())) {}
34 }
35 34
36 void Add(const Code& code) { 35 void Add(const Code& code) {
37 if (current_.IsNull()) { 36 if (current_.IsNull()) {
38 return; 37 return;
39 } 38 }
40 if (!Contained(code, previous_) || Contained(code, current_)) { 39 if (!Contained(code, previous_) || Contained(code, current_)) {
41 return; 40 return;
42 } 41 }
43 current_.Add(code); 42 current_.Add(code);
44 } 43 }
45 44
46 void UpdateIsolate(Isolate* isolate) { 45 void UpdateIsolate(Isolate* isolate) {
47 intptr_t size_before = SizeOf(previous_); 46 intptr_t size_before = SizeOf(previous_);
48 intptr_t size_after = SizeOf(current_); 47 intptr_t size_after = SizeOf(current_);
49 if ((size_before > 0) && FLAG_trace_profiler) { 48 if ((size_before > 0) && FLAG_trace_profiler) {
50 intptr_t length_before = previous_.Length(); 49 intptr_t length_before = previous_.Length();
51 intptr_t length_after = current_.Length(); 50 intptr_t length_after = current_.Length();
52 OS::Print("Updating isolate deoptimized code array: " 51 OS::Print(
53 "%" Pd " -> %" Pd " [%" Pd " -> %" Pd "]\n", 52 "Updating isolate deoptimized code array: "
54 size_before, size_after, length_before, length_after); 53 "%" Pd " -> %" Pd " [%" Pd " -> %" Pd "]\n",
54 size_before, size_after, length_before, length_after);
55 } 55 }
56 isolate->set_deoptimized_code_array(current_); 56 isolate->set_deoptimized_code_array(current_);
57 } 57 }
58 58
59 private: 59 private:
60 bool Contained(const Code& code, const GrowableObjectArray& array) { 60 bool Contained(const Code& code, const GrowableObjectArray& array) {
61 if (array.IsNull() || code.IsNull()) { 61 if (array.IsNull() || code.IsNull()) {
62 return false; 62 return false;
63 } 63 }
64 NoSafepointScope no_safepoint_scope; 64 NoSafepointScope no_safepoint_scope;
(...skipping 21 matching lines...) Expand all
86 86
87 // Array holding code that is being kept around only for the profiler. 87 // Array holding code that is being kept around only for the profiler.
88 const GrowableObjectArray& previous_; 88 const GrowableObjectArray& previous_;
89 // Array holding code that should continue to be kept around for the profiler. 89 // Array holding code that should continue to be kept around for the profiler.
90 const GrowableObjectArray& current_; 90 const GrowableObjectArray& current_;
91 }; 91 };
92 92
93 93
94 ProfileFunctionSourcePosition::ProfileFunctionSourcePosition( 94 ProfileFunctionSourcePosition::ProfileFunctionSourcePosition(
95 TokenPosition token_pos) 95 TokenPosition token_pos)
96 : token_pos_(token_pos), 96 : token_pos_(token_pos), exclusive_ticks_(0), inclusive_ticks_(0) {}
97 exclusive_ticks_(0),
98 inclusive_ticks_(0) {
99 }
100 97
101 98
102 void ProfileFunctionSourcePosition::Tick(bool exclusive) { 99 void ProfileFunctionSourcePosition::Tick(bool exclusive) {
103 if (exclusive) { 100 if (exclusive) {
104 exclusive_ticks_++; 101 exclusive_ticks_++;
105 } else { 102 } else {
106 inclusive_ticks_++; 103 inclusive_ticks_++;
107 } 104 }
108 } 105 }
109 106
110 107
111 ProfileFunction::ProfileFunction(Kind kind, 108 ProfileFunction::ProfileFunction(Kind kind,
112 const char* name, 109 const char* name,
113 const Function& function, 110 const Function& function,
114 const intptr_t table_index) 111 const intptr_t table_index)
115 : kind_(kind), 112 : kind_(kind),
116 name_(name), 113 name_(name),
117 function_(Function::ZoneHandle(function.raw())), 114 function_(Function::ZoneHandle(function.raw())),
118 table_index_(table_index), 115 table_index_(table_index),
119 profile_codes_(0), 116 profile_codes_(0),
120 source_position_ticks_(0), 117 source_position_ticks_(0),
121 exclusive_ticks_(0), 118 exclusive_ticks_(0),
122 inclusive_ticks_(0), 119 inclusive_ticks_(0),
123 inclusive_serial_(-1) { 120 inclusive_serial_(-1) {
124 ASSERT((kind_ != kDartFunction) || !function_.IsNull()); 121 ASSERT((kind_ != kDartFunction) || !function_.IsNull());
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 } 263 }
267 if (source_position_ticks_.length() != 1) { 264 if (source_position_ticks_.length() != 1) {
268 return false; 265 return false;
269 } 266 }
270 *pfsp = source_position_ticks_[0]; 267 *pfsp = source_position_ticks_[0];
271 return true; 268 return true;
272 } 269 }
273 270
274 271
275 ProfileCodeAddress::ProfileCodeAddress(uword pc) 272 ProfileCodeAddress::ProfileCodeAddress(uword pc)
276 : pc_(pc), 273 : pc_(pc), exclusive_ticks_(0), inclusive_ticks_(0) {}
277 exclusive_ticks_(0),
278 inclusive_ticks_(0) {
279 }
280 274
281 275
282 void ProfileCodeAddress::Tick(bool exclusive) { 276 void ProfileCodeAddress::Tick(bool exclusive) {
283 if (exclusive) { 277 if (exclusive) {
284 exclusive_ticks_++; 278 exclusive_ticks_++;
285 } else { 279 } else {
286 inclusive_ticks_++; 280 inclusive_ticks_++;
287 } 281 }
288 } 282 }
289 283
290 284
291 ProfileCode::ProfileCode(Kind kind, 285 ProfileCode::ProfileCode(Kind kind,
292 uword start, 286 uword start,
293 uword end, 287 uword end,
294 int64_t timestamp, 288 int64_t timestamp,
295 const Code& code) 289 const Code& code)
296 : kind_(kind), 290 : kind_(kind),
297 start_(start), 291 start_(start),
298 end_(end), 292 end_(end),
299 exclusive_ticks_(0), 293 exclusive_ticks_(0),
300 inclusive_ticks_(0), 294 inclusive_ticks_(0),
301 inclusive_serial_(-1), 295 inclusive_serial_(-1),
302 code_(code), 296 code_(code),
303 name_(NULL), 297 name_(NULL),
304 compile_timestamp_(0), 298 compile_timestamp_(0),
305 function_(NULL), 299 function_(NULL),
306 code_table_index_(-1), 300 code_table_index_(-1),
307 address_ticks_(0) { 301 address_ticks_(0) {}
308 }
309 302
310 303
311 void ProfileCode::AdjustExtent(uword start, uword end) { 304 void ProfileCode::AdjustExtent(uword start, uword end) {
312 if (start < start_) { 305 if (start < start_) {
313 start_ = start; 306 start_ = start;
314 } 307 }
315 if (end > end_) { 308 if (end > end_) {
316 end_ = end; 309 end_ = end;
317 } 310 }
318 ASSERT(start_ < end_); 311 ASSERT(start_ < end_);
319 } 312 }
320 313
321 314
322 bool ProfileCode::Overlaps(const ProfileCode* other) const { 315 bool ProfileCode::Overlaps(const ProfileCode* other) const {
323 ASSERT(other != NULL); 316 ASSERT(other != NULL);
324 return other->Contains(start_) || 317 return other->Contains(start_) || other->Contains(end_ - 1) ||
325 other->Contains(end_ - 1) || 318 Contains(other->start()) || Contains(other->end() - 1);
326 Contains(other->start()) ||
327 Contains(other->end() - 1);
328 } 319 }
329 320
330 321
331 bool ProfileCode::IsOptimizedDart() const { 322 bool ProfileCode::IsOptimizedDart() const {
332 return !code_.IsNull() && code_.is_optimized(); 323 return !code_.IsNull() && code_.is_optimized();
333 } 324 }
334 325
335 326
336 void ProfileCode::SetName(const char* name) { 327 void ProfileCode::SetName(const char* name) {
337 if (name == NULL) { 328 if (name == NULL) {
338 name_ = NULL; 329 name_ = NULL;
339 } 330 }
340 intptr_t len = strlen(name); 331 intptr_t len = strlen(name);
341 name_ = Thread::Current()->zone()->Alloc<char>(len + 1); 332 name_ = Thread::Current()->zone()->Alloc<char>(len + 1);
342 strncpy(name_, name, len); 333 strncpy(name_, name, len);
343 name_[len] = '\0'; 334 name_[len] = '\0';
344 } 335 }
345 336
346 337
347 void ProfileCode::GenerateAndSetSymbolName(const char* prefix) { 338 void ProfileCode::GenerateAndSetSymbolName(const char* prefix) {
348 const intptr_t kBuffSize = 512; 339 const intptr_t kBuffSize = 512;
349 char buff[kBuffSize]; 340 char buff[kBuffSize];
350 OS::SNPrint(&buff[0], kBuffSize-1, "%s [%" Px ", %" Px ")", 341 OS::SNPrint(&buff[0], kBuffSize - 1, "%s [%" Px ", %" Px ")", prefix, start(),
351 prefix, start(), end()); 342 end());
352 SetName(buff); 343 SetName(buff);
353 } 344 }
354 345
355 346
356 void ProfileCode::Tick(uword pc, bool exclusive, intptr_t serial) { 347 void ProfileCode::Tick(uword pc, bool exclusive, intptr_t serial) {
357 // If exclusive is set, tick it. 348 // If exclusive is set, tick it.
358 if (exclusive) { 349 if (exclusive) {
359 exclusive_ticks_++; 350 exclusive_ticks_++;
360 TickAddress(pc, true); 351 TickAddress(pc, true);
361 } 352 }
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 } 511 }
521 } 512 }
522 513
523 514
524 class ProfileFunctionTable : public ZoneAllocated { 515 class ProfileFunctionTable : public ZoneAllocated {
525 public: 516 public:
526 ProfileFunctionTable() 517 ProfileFunctionTable()
527 : null_function_(Function::ZoneHandle()), 518 : null_function_(Function::ZoneHandle()),
528 unknown_function_(NULL), 519 unknown_function_(NULL),
529 table_(8) { 520 table_(8) {
530 unknown_function_ = Add(ProfileFunction::kUnknownFunction, 521 unknown_function_ =
531 "<unknown Dart function>"); 522 Add(ProfileFunction::kUnknownFunction, "<unknown Dart function>");
532 } 523 }
533 524
534 ProfileFunction* LookupOrAdd(const Function& function) { 525 ProfileFunction* LookupOrAdd(const Function& function) {
535 ASSERT(!function.IsNull()); 526 ASSERT(!function.IsNull());
536 ProfileFunction* profile_function = Lookup(function); 527 ProfileFunction* profile_function = Lookup(function);
537 if (profile_function != NULL) { 528 if (profile_function != NULL) {
538 return profile_function; 529 return profile_function;
539 } 530 }
540 return Add(function); 531 return Add(function);
541 } 532 }
(...skipping 19 matching lines...) Expand all
561 ProfileFunction* AddNative(uword start_address, const char* name) { 552 ProfileFunction* AddNative(uword start_address, const char* name) {
562 // TODO(johnmccutchan): Canonicalize ProfileFunctions for natives. 553 // TODO(johnmccutchan): Canonicalize ProfileFunctions for natives.
563 return Add(ProfileFunction::kNativeFunction, name); 554 return Add(ProfileFunction::kNativeFunction, name);
564 } 555 }
565 556
566 // No protection against being called more tha once for the same stub. 557 // No protection against being called more tha once for the same stub.
567 ProfileFunction* AddStub(uword start_address, const char* name) { 558 ProfileFunction* AddStub(uword start_address, const char* name) {
568 return Add(ProfileFunction::kStubFunction, name); 559 return Add(ProfileFunction::kStubFunction, name);
569 } 560 }
570 561
571 intptr_t length() const { 562 intptr_t length() const { return table_.length(); }
572 return table_.length();
573 }
574 563
575 ProfileFunction* At(intptr_t i) const { 564 ProfileFunction* At(intptr_t i) const {
576 ASSERT(i >= 0); 565 ASSERT(i >= 0);
577 ASSERT(i < length()); 566 ASSERT(i < length());
578 return table_[i]; 567 return table_[i];
579 } 568 }
580 569
581 private: 570 private:
582 ProfileFunction* Add(ProfileFunction::Kind kind, const char* name) { 571 ProfileFunction* Add(ProfileFunction::Kind kind, const char* name) {
583 ASSERT(kind != ProfileFunction::kDartFunction); 572 ASSERT(kind != ProfileFunction::kDartFunction);
584 ASSERT(name != NULL); 573 ASSERT(name != NULL);
585 ProfileFunction* profile_function = 574 ProfileFunction* profile_function =
586 new ProfileFunction(kind, 575 new ProfileFunction(kind, name, null_function_, table_.length());
587 name,
588 null_function_,
589 table_.length());
590 table_.Add(profile_function); 576 table_.Add(profile_function);
591 return profile_function; 577 return profile_function;
592 } 578 }
593 579
594 ProfileFunction* Add(const Function& function) { 580 ProfileFunction* Add(const Function& function) {
595 ASSERT(Lookup(function) == NULL); 581 ASSERT(Lookup(function) == NULL);
596 ProfileFunction* profile_function = 582 ProfileFunction* profile_function = new ProfileFunction(
597 new ProfileFunction(ProfileFunction::kDartFunction, 583 ProfileFunction::kDartFunction, NULL, function, table_.length());
598 NULL,
599 function,
600 table_.length());
601 table_.Add(profile_function); 584 table_.Add(profile_function);
602 function_hash_.Insert(profile_function); 585 function_hash_.Insert(profile_function);
603 return profile_function; 586 return profile_function;
604 } 587 }
605 588
606 // Needed for DirectChainedHashMap. 589 // Needed for DirectChainedHashMap.
607 struct ProfileFunctionTableTrait { 590 struct ProfileFunctionTableTrait {
608 typedef ProfileFunction* Value; 591 typedef ProfileFunction* Value;
609 typedef const Function* Key; 592 typedef const Function* Key;
610 typedef ProfileFunction* Pair; 593 typedef ProfileFunction* Pair;
611 594
612 static Key KeyOf(Pair kv) { 595 static Key KeyOf(Pair kv) { return kv->function(); }
613 return kv->function();
614 }
615 596
616 static Value ValueOf(Pair kv) { 597 static Value ValueOf(Pair kv) { return kv; }
617 return kv;
618 }
619 598
620 static inline intptr_t Hashcode(Key key) { 599 static inline intptr_t Hashcode(Key key) { return key->Hash(); }
621 return key->Hash();
622 }
623 600
624 static inline bool IsKeyEqual(Pair kv, Key key) { 601 static inline bool IsKeyEqual(Pair kv, Key key) {
625 return kv->function()->raw() == key->raw(); 602 return kv->function()->raw() == key->raw();
626 } 603 }
627 }; 604 };
628 605
629 const Function& null_function_; 606 const Function& null_function_;
630 ProfileFunction* unknown_function_; 607 ProfileFunction* unknown_function_;
631 ZoneGrowableArray<ProfileFunction*> table_; 608 ZoneGrowableArray<ProfileFunction*> table_;
632 DirectChainedHashMap<ProfileFunctionTableTrait> function_hash_; 609 DirectChainedHashMap<ProfileFunctionTableTrait> function_hash_;
(...skipping 27 matching lines...) Expand all
660 // Lazily set generated name. 637 // Lazily set generated name.
661 GenerateAndSetSymbolName("[Native]"); 638 GenerateAndSetSymbolName("[Native]");
662 } 639 }
663 function = table->AddNative(start(), name()); 640 function = table->AddNative(start(), name());
664 } else if (kind() == kTagCode) { 641 } else if (kind() == kTagCode) {
665 if (name() == NULL) { 642 if (name() == NULL) {
666 if (UserTags::IsUserTag(start())) { 643 if (UserTags::IsUserTag(start())) {
667 const char* tag_name = UserTags::TagName(start()); 644 const char* tag_name = UserTags::TagName(start());
668 ASSERT(tag_name != NULL); 645 ASSERT(tag_name != NULL);
669 SetName(tag_name); 646 SetName(tag_name);
670 } else if (VMTag::IsVMTag(start()) || 647 } else if (VMTag::IsVMTag(start()) || VMTag::IsRuntimeEntryTag(start()) ||
671 VMTag::IsRuntimeEntryTag(start()) ||
672 VMTag::IsNativeEntryTag(start())) { 648 VMTag::IsNativeEntryTag(start())) {
673 const char* tag_name = VMTag::TagName(start()); 649 const char* tag_name = VMTag::TagName(start());
674 ASSERT(tag_name != NULL); 650 ASSERT(tag_name != NULL);
675 SetName(tag_name); 651 SetName(tag_name);
676 } else { 652 } else {
677 switch (start()) { 653 switch (start()) {
678 case VMTag::kRootTagId: 654 case VMTag::kRootTagId:
679 SetName("Root"); 655 SetName("Root");
680 break; 656 break;
681 case VMTag::kTruncatedTagId: 657 case VMTag::kTruncatedTagId:
(...skipping 12 matching lines...) Expand all
694 SetName("[Native Code]"); 670 SetName("[Native Code]");
695 break; 671 break;
696 case VMTag::kInlineStartCodeTagId: 672 case VMTag::kInlineStartCodeTagId:
697 SetName("[Inline Start]"); 673 SetName("[Inline Start]");
698 break; 674 break;
699 case VMTag::kInlineEndCodeTagId: 675 case VMTag::kInlineEndCodeTagId:
700 SetName("[Inline End]"); 676 SetName("[Inline End]");
701 break; 677 break;
702 default: 678 default:
703 UNIMPLEMENTED(); 679 UNIMPLEMENTED();
704 break; 680 break;
705 } 681 }
706 } 682 }
707 } 683 }
708 function = table->AddTag(start(), name()); 684 function = table->AddTag(start(), name());
709 } else { 685 } else {
710 UNREACHABLE(); 686 UNREACHABLE();
711 } 687 }
712 ASSERT(function != NULL); 688 ASSERT(function != NULL);
713 689
714 function->AddProfileCode(code_table_index()); 690 function->AddProfileCode(code_table_index());
715 691
716 function_ = function; 692 function_ = function;
717 return function_; 693 return function_;
718 } 694 }
719 695
720 696
721 typedef bool (*RangeCompare)(uword pc, uword region_start, uword region_end); 697 typedef bool (*RangeCompare)(uword pc, uword region_start, uword region_end);
722 698
723 class ProfileCodeTable : public ZoneAllocated { 699 class ProfileCodeTable : public ZoneAllocated {
724 public: 700 public:
725 ProfileCodeTable() 701 ProfileCodeTable() : table_(8) {}
726 : table_(8) {
727 }
728 702
729 intptr_t length() const { return table_.length(); } 703 intptr_t length() const { return table_.length(); }
730 704
731 ProfileCode* At(intptr_t index) const { 705 ProfileCode* At(intptr_t index) const {
732 ASSERT(index >= 0); 706 ASSERT(index >= 0);
733 ASSERT(index < length()); 707 ASSERT(index < length());
734 return table_[index]; 708 return table_[index];
735 } 709 }
736 710
737 // Find the table index to the ProfileCode containing pc. 711 // Find the table index to the ProfileCode containing pc.
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 } 813 }
840 814
841 static bool CompareUpperBound(uword pc, uword start, uword end) { 815 static bool CompareUpperBound(uword pc, uword start, uword end) {
842 return pc >= end; 816 return pc >= end;
843 } 817 }
844 818
845 static bool CompareLowerBound(uword pc, uword start, uword end) { 819 static bool CompareLowerBound(uword pc, uword start, uword end) {
846 return end <= pc; 820 return end <= pc;
847 } 821 }
848 822
849 void HandleOverlap(ProfileCode* existing, ProfileCode* code, 823 void HandleOverlap(ProfileCode* existing,
850 uword start, uword end) { 824 ProfileCode* code,
825 uword start,
826 uword end) {
851 // We should never see overlapping Dart code regions. 827 // We should never see overlapping Dart code regions.
852 ASSERT(existing->kind() != ProfileCode::kDartCode); 828 ASSERT(existing->kind() != ProfileCode::kDartCode);
853 // We should never see overlapping Tag code regions. 829 // We should never see overlapping Tag code regions.
854 ASSERT(existing->kind() != ProfileCode::kTagCode); 830 ASSERT(existing->kind() != ProfileCode::kTagCode);
855 // When code regions overlap, they should be of the same kind. 831 // When code regions overlap, they should be of the same kind.
856 ASSERT(existing->kind() == code->kind()); 832 ASSERT(existing->kind() == code->kind());
857 existing->AdjustExtent(start, end); 833 existing->AdjustExtent(start, end);
858 } 834 }
859 835
860 void VerifyOrder() { 836 void VerifyOrder() {
861 const intptr_t length = table_.length(); 837 const intptr_t length = table_.length();
862 if (length == 0) { 838 if (length == 0) {
863 return; 839 return;
864 } 840 }
865 uword last = table_[0]->end(); 841 uword last = table_[0]->end();
866 for (intptr_t i = 1; i < length; i++) { 842 for (intptr_t i = 1; i < length; i++) {
867 ProfileCode* a = table_[i]; 843 ProfileCode* a = table_[i];
868 ASSERT(last <= a->start()); 844 ASSERT(last <= a->start());
869 last = a->end(); 845 last = a->end();
870 } 846 }
871 } 847 }
872 848
873 void VerifyOverlap() { 849 void VerifyOverlap() {
874 const intptr_t length = table_.length(); 850 const intptr_t length = table_.length();
875 for (intptr_t i = 0; i < length; i++) { 851 for (intptr_t i = 0; i < length; i++) {
876 ProfileCode* a = table_[i]; 852 ProfileCode* a = table_[i];
877 for (intptr_t j = i+1; j < length; j++) { 853 for (intptr_t j = i + 1; j < length; j++) {
878 ProfileCode* b = table_[j]; 854 ProfileCode* b = table_[j];
879 ASSERT(!a->Contains(b->start()) && 855 ASSERT(!a->Contains(b->start()) && !a->Contains(b->end() - 1) &&
880 !a->Contains(b->end() - 1) && 856 !b->Contains(a->start()) && !b->Contains(a->end() - 1));
881 !b->Contains(a->start()) &&
882 !b->Contains(a->end() - 1));
883 } 857 }
884 } 858 }
885 } 859 }
886 860
887 ZoneGrowableArray<ProfileCode*> table_; 861 ZoneGrowableArray<ProfileCode*> table_;
888 }; 862 };
889 863
890 864
891 ProfileTrieNode::ProfileTrieNode(intptr_t table_index) 865 ProfileTrieNode::ProfileTrieNode(intptr_t table_index)
892 : table_index_(table_index), 866 : table_index_(table_index), count_(0), children_(0), frame_id_(-1) {
893 count_(0),
894 children_(0),
895 frame_id_(-1) {
896 ASSERT(table_index_ >= 0); 867 ASSERT(table_index_ >= 0);
897 } 868 }
898 869
899 870
900 ProfileTrieNode::~ProfileTrieNode() { 871 ProfileTrieNode::~ProfileTrieNode() {}
901 }
902 872
903 873
904 void ProfileTrieNode::SortChildren() { 874 void ProfileTrieNode::SortChildren() {
905 children_.Sort(ProfileTrieNodeCompare); 875 children_.Sort(ProfileTrieNodeCompare);
906 // Recurse. 876 // Recurse.
907 for (intptr_t i = 0; i < children_.length(); i++) { 877 for (intptr_t i = 0; i < children_.length(); i++) {
908 children_[i]->SortChildren(); 878 children_[i]->SortChildren();
909 } 879 }
910 } 880 }
911 881
912 882
913 intptr_t ProfileTrieNode::IndexOf(ProfileTrieNode* node) { 883 intptr_t ProfileTrieNode::IndexOf(ProfileTrieNode* node) {
914 for (intptr_t i = 0; i < children_.length(); i++) { 884 for (intptr_t i = 0; i < children_.length(); i++) {
915 if (children_[i] == node) { 885 if (children_[i] == node) {
916 return i; 886 return i;
917 } 887 }
918 } 888 }
919 return -1; 889 return -1;
920 } 890 }
921 891
922 892
923 class ProfileCodeTrieNode : public ProfileTrieNode { 893 class ProfileCodeTrieNode : public ProfileTrieNode {
924 public: 894 public:
925 explicit ProfileCodeTrieNode(intptr_t table_index) 895 explicit ProfileCodeTrieNode(intptr_t table_index)
926 : ProfileTrieNode(table_index) { 896 : ProfileTrieNode(table_index) {}
927 }
928 897
929 void PrintToJSONArray(JSONArray* array) const { 898 void PrintToJSONArray(JSONArray* array) const {
930 ASSERT(array != NULL); 899 ASSERT(array != NULL);
931 // Write CodeRegion index. 900 // Write CodeRegion index.
932 array->AddValue(table_index()); 901 array->AddValue(table_index());
933 // Write count. 902 // Write count.
934 array->AddValue(count()); 903 array->AddValue(count());
935 // Write number of children. 904 // Write number of children.
936 intptr_t child_count = NumChildren(); 905 intptr_t child_count = NumChildren();
937 array->AddValue(child_count); 906 array->AddValue(child_count);
(...skipping 26 matching lines...) Expand all
964 children_.Add(reinterpret_cast<ProfileTrieNode*>(child)); 933 children_.Add(reinterpret_cast<ProfileTrieNode*>(child));
965 } 934 }
966 return child; 935 return child;
967 } 936 }
968 }; 937 };
969 938
970 939
971 class ProfileFunctionTrieNodeCode { 940 class ProfileFunctionTrieNodeCode {
972 public: 941 public:
973 explicit ProfileFunctionTrieNodeCode(intptr_t index) 942 explicit ProfileFunctionTrieNodeCode(intptr_t index)
974 : code_index_(index), 943 : code_index_(index), ticks_(0) {}
975 ticks_(0) {
976 }
977 944
978 intptr_t index() const { 945 intptr_t index() const { return code_index_; }
979 return code_index_;
980 }
981 946
982 void Tick() { 947 void Tick() { ticks_++; }
983 ticks_++;
984 }
985 948
986 intptr_t ticks() const { 949 intptr_t ticks() const { return ticks_; }
987 return ticks_;
988 }
989 950
990 private: 951 private:
991 intptr_t code_index_; 952 intptr_t code_index_;
992 intptr_t ticks_; 953 intptr_t ticks_;
993 }; 954 };
994 955
995 956
996 class ProfileFunctionTrieNode : public ProfileTrieNode { 957 class ProfileFunctionTrieNode : public ProfileTrieNode {
997 public: 958 public:
998 explicit ProfileFunctionTrieNode(intptr_t table_index) 959 explicit ProfileFunctionTrieNode(intptr_t table_index)
999 : ProfileTrieNode(table_index), 960 : ProfileTrieNode(table_index), code_objects_(1) {}
1000 code_objects_(1) {
1001 }
1002 961
1003 void PrintToJSONArray(JSONArray* array) const { 962 void PrintToJSONArray(JSONArray* array) const {
1004 ASSERT(array != NULL); 963 ASSERT(array != NULL);
1005 // Write CodeRegion index. 964 // Write CodeRegion index.
1006 array->AddValue(table_index()); 965 array->AddValue(table_index());
1007 // Write count. 966 // Write count.
1008 array->AddValue(count()); 967 array->AddValue(count());
1009 // Write number of code objects. 968 // Write number of code objects.
1010 intptr_t code_count = code_objects_.length(); 969 intptr_t code_count = code_objects_.length();
1011 array->AddValue(code_count); 970 array->AddValue(code_count);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1062 code_objects_.Add(code_object); 1021 code_objects_.Add(code_object);
1063 } 1022 }
1064 1023
1065 private: 1024 private:
1066 ZoneGrowableArray<ProfileFunctionTrieNodeCode> code_objects_; 1025 ZoneGrowableArray<ProfileFunctionTrieNodeCode> code_objects_;
1067 }; 1026 };
1068 1027
1069 1028
1070 class ProfileCodeInlinedFunctionsCache : public ValueObject { 1029 class ProfileCodeInlinedFunctionsCache : public ValueObject {
1071 public: 1030 public:
1072 ProfileCodeInlinedFunctionsCache() 1031 ProfileCodeInlinedFunctionsCache() : cache_cursor_(0), last_hit_(0) {
1073 : cache_cursor_(0),
1074 last_hit_(0) {
1075 for (intptr_t i = 0; i < kCacheSize; i++) { 1032 for (intptr_t i = 0; i < kCacheSize; i++) {
1076 cache_[i].Reset(); 1033 cache_[i].Reset();
1077 } 1034 }
1078 cache_hit_ = 0; 1035 cache_hit_ = 0;
1079 cache_miss_ = 0; 1036 cache_miss_ = 0;
1080 } 1037 }
1081 1038
1082 ~ProfileCodeInlinedFunctionsCache() { 1039 ~ProfileCodeInlinedFunctionsCache() {
1083 if (FLAG_trace_profiler) { 1040 if (FLAG_trace_profiler) {
1084 intptr_t total = cache_hit_ + cache_miss_; 1041 intptr_t total = cache_hit_ + cache_miss_;
1085 OS::Print("LOOKUPS: %" Pd " HITS: %" Pd " MISSES: %" Pd "\n", 1042 OS::Print("LOOKUPS: %" Pd " HITS: %" Pd " MISSES: %" Pd "\n", total,
1086 total, 1043 cache_hit_, cache_miss_);
1087 cache_hit_,
1088 cache_miss_);
1089 } 1044 }
1090 } 1045 }
1091 1046
1092 void Get(uword pc, 1047 void Get(uword pc,
1093 const Code& code, 1048 const Code& code,
1094 ProcessedSample* sample, 1049 ProcessedSample* sample,
1095 intptr_t frame_index, 1050 intptr_t frame_index,
1096 // Outputs: 1051 // Outputs:
1097 GrowableArray<Function*>** inlined_functions, 1052 GrowableArray<Function*>** inlined_functions,
1098 GrowableArray<TokenPosition>** inlined_token_positions, 1053 GrowableArray<TokenPosition>** inlined_token_positions,
1099 TokenPosition* token_position) { 1054 TokenPosition* token_position) {
1100 const intptr_t offset = OffsetForPC(pc, code, sample, frame_index); 1055 const intptr_t offset = OffsetForPC(pc, code, sample, frame_index);
1101 if (FindInCache(pc, 1056 if (FindInCache(pc, offset, inlined_functions, inlined_token_positions,
1102 offset,
1103 inlined_functions,
1104 inlined_token_positions,
1105 token_position)) { 1057 token_position)) {
1106 // Found in cache. 1058 // Found in cache.
1107 return; 1059 return;
1108 } 1060 }
1109 Add(pc, code, sample, frame_index, 1061 Add(pc, code, sample, frame_index, inlined_functions,
1110 inlined_functions, inlined_token_positions, token_position); 1062 inlined_token_positions, token_position);
1111 } 1063 }
1112 1064
1113 private: 1065 private:
1114 bool FindInCache(uword pc, 1066 bool FindInCache(uword pc,
1115 intptr_t offset, 1067 intptr_t offset,
1116 GrowableArray<Function*>** inlined_functions, 1068 GrowableArray<Function*>** inlined_functions,
1117 GrowableArray<TokenPosition>** inlined_token_positions, 1069 GrowableArray<TokenPosition>** inlined_token_positions,
1118 TokenPosition* token_position) { 1070 TokenPosition* token_position) {
1119 // Simple linear scan. 1071 // Simple linear scan.
1120 for (intptr_t i = 0; i < kCacheSize; i++) { 1072 for (intptr_t i = 0; i < kCacheSize; i++) {
(...skipping 23 matching lines...) Expand all
1144 ProcessedSample* sample, 1096 ProcessedSample* sample,
1145 intptr_t frame_index, 1097 intptr_t frame_index,
1146 // Outputs: 1098 // Outputs:
1147 GrowableArray<Function*>** inlined_functions, 1099 GrowableArray<Function*>** inlined_functions,
1148 GrowableArray<TokenPosition>** inlined_token_positions, 1100 GrowableArray<TokenPosition>** inlined_token_positions,
1149 TokenPosition* token_position) { 1101 TokenPosition* token_position) {
1150 const intptr_t offset = OffsetForPC(pc, code, sample, frame_index); 1102 const intptr_t offset = OffsetForPC(pc, code, sample, frame_index);
1151 CacheEntry* cache_entry = &cache_[NextFreeIndex()]; 1103 CacheEntry* cache_entry = &cache_[NextFreeIndex()];
1152 cache_entry->pc = pc; 1104 cache_entry->pc = pc;
1153 cache_entry->offset = offset; 1105 cache_entry->offset = offset;
1154 code.GetInlinedFunctionsAt(offset, 1106 code.GetInlinedFunctionsAt(offset, &(cache_entry->inlined_functions),
1155 &(cache_entry->inlined_functions),
1156 &(cache_entry->inlined_token_positions)); 1107 &(cache_entry->inlined_token_positions));
1157 cache_entry->token_position = code.GetTokenPositionAt(offset); 1108 cache_entry->token_position = code.GetTokenPositionAt(offset);
1158 *token_position = (cache_entry->token_position); 1109 *token_position = (cache_entry->token_position);
1159 if (cache_entry->inlined_functions.length() == 0) { 1110 if (cache_entry->inlined_functions.length() == 0) {
1160 *inlined_functions = NULL; 1111 *inlined_functions = NULL;
1161 *inlined_token_positions = NULL; 1112 *inlined_token_positions = NULL;
1162 return; 1113 return;
1163 } 1114 }
1164 // The inlined token position table does not include the token position 1115 // The inlined token position table does not include the token position
1165 // of the final call. Insert it at the beginning because the table. 1116 // of the final call. Insert it at the beginning because the table.
1166 // is reversed. 1117 // is reversed.
1167 cache_entry->inlined_token_positions.InsertAt( 1118 cache_entry->inlined_token_positions.InsertAt(0,
1168 0, 1119 cache_entry->token_position);
1169 cache_entry->token_position);
1170 1120
1171 // Write outputs. 1121 // Write outputs.
1172 *inlined_functions = &(cache_entry->inlined_functions); 1122 *inlined_functions = &(cache_entry->inlined_functions);
1173 *inlined_token_positions = &(cache_entry->inlined_token_positions); 1123 *inlined_token_positions = &(cache_entry->inlined_token_positions);
1174 } 1124 }
1175 1125
1176 intptr_t NextFreeIndex() { 1126 intptr_t NextFreeIndex() {
1177 cache_cursor_ = (cache_cursor_ + 1) % kCacheSize; 1127 cache_cursor_ = (cache_cursor_ + 1) % kCacheSize;
1178 return cache_cursor_; 1128 return cache_cursor_;
1179 } 1129 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 BuildCodeTrie(Profile::kExclusiveCode); 1218 BuildCodeTrie(Profile::kExclusiveCode);
1269 BuildCodeTrie(Profile::kInclusiveCode); 1219 BuildCodeTrie(Profile::kInclusiveCode);
1270 1220
1271 BuildFunctionTrie(Profile::kExclusiveFunction); 1221 BuildFunctionTrie(Profile::kExclusiveFunction);
1272 BuildFunctionTrie(Profile::kInclusiveFunction); 1222 BuildFunctionTrie(Profile::kInclusiveFunction);
1273 } 1223 }
1274 1224
1275 private: 1225 private:
1276 // Returns true if |frame_index| in |sample| is using CPU. 1226 // Returns true if |frame_index| in |sample| is using CPU.
1277 static bool IsExecutingFrame(ProcessedSample* sample, intptr_t frame_index) { 1227 static bool IsExecutingFrame(ProcessedSample* sample, intptr_t frame_index) {
1278 return (frame_index == 0) && (sample->first_frame_executing() || 1228 return (frame_index == 0) &&
1279 sample->IsAllocationSample()); 1229 (sample->first_frame_executing() || sample->IsAllocationSample());
1280 } 1230 }
1281 1231
1282 static bool IsInclusiveTrie(Profile::TrieKind kind) { 1232 static bool IsInclusiveTrie(Profile::TrieKind kind) {
1283 return (kind == Profile::kInclusiveFunction) || 1233 return (kind == Profile::kInclusiveFunction) ||
1284 (kind == Profile::kInclusiveCode); 1234 (kind == Profile::kInclusiveCode);
1285 } 1235 }
1286 1236
1287 void Setup() { 1237 void Setup() {
1288 profile_->live_code_ = new ProfileCodeTable(); 1238 profile_->live_code_ = new ProfileCodeTable();
1289 profile_->dead_code_ = new ProfileCodeTable(); 1239 profile_->dead_code_ = new ProfileCodeTable();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1333 ASSERT(isolate != NULL); 1283 ASSERT(isolate != NULL);
1334 1284
1335 // Build the live code table eagerly by populating it with code objects 1285 // Build the live code table eagerly by populating it with code objects
1336 // from the processed sample buffer. 1286 // from the processed sample buffer.
1337 const CodeLookupTable& code_lookup_table = samples_->code_lookup_table(); 1287 const CodeLookupTable& code_lookup_table = samples_->code_lookup_table();
1338 for (intptr_t i = 0; i < code_lookup_table.length(); i++) { 1288 for (intptr_t i = 0; i < code_lookup_table.length(); i++) {
1339 const CodeDescriptor* descriptor = code_lookup_table.At(i); 1289 const CodeDescriptor* descriptor = code_lookup_table.At(i);
1340 ASSERT(descriptor != NULL); 1290 ASSERT(descriptor != NULL);
1341 const Code& code = Code::Handle(descriptor->code()); 1291 const Code& code = Code::Handle(descriptor->code());
1342 ASSERT(!code.IsNull()); 1292 ASSERT(!code.IsNull());
1343 RegisterLiveProfileCode( 1293 RegisterLiveProfileCode(new ProfileCode(
1344 new ProfileCode(ProfileCode::kDartCode, 1294 ProfileCode::kDartCode, code.PayloadStart(),
1345 code.PayloadStart(), 1295 code.PayloadStart() + code.Size(), code.compile_timestamp(), code));
1346 code.PayloadStart() + code.Size(),
1347 code.compile_timestamp(),
1348 code));
1349 } 1296 }
1350 1297
1351 // Iterate over samples. 1298 // Iterate over samples.
1352 for (intptr_t sample_index = 0; 1299 for (intptr_t sample_index = 0; sample_index < samples_->length();
1353 sample_index < samples_->length();
1354 sample_index++) { 1300 sample_index++) {
1355 ProcessedSample* sample = samples_->At(sample_index); 1301 ProcessedSample* sample = samples_->At(sample_index);
1356 const int64_t timestamp = sample->timestamp(); 1302 const int64_t timestamp = sample->timestamp();
1357 1303
1358 // This is our first pass over the sample buffer, use this as an 1304 // This is our first pass over the sample buffer, use this as an
1359 // opportunity to determine the min and max time ranges of this profile. 1305 // opportunity to determine the min and max time ranges of this profile.
1360 UpdateMinMaxTimes(timestamp); 1306 UpdateMinMaxTimes(timestamp);
1361 1307
1362 // Make sure VM tag exists. 1308 // Make sure VM tag exists.
1363 if (VMTag::IsNativeEntryTag(sample->vm_tag())) { 1309 if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
1364 RegisterProfileCodeTag(VMTag::kNativeTagId); 1310 RegisterProfileCodeTag(VMTag::kNativeTagId);
1365 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { 1311 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
1366 RegisterProfileCodeTag(VMTag::kRuntimeTagId); 1312 RegisterProfileCodeTag(VMTag::kRuntimeTagId);
1367 } 1313 }
1368 RegisterProfileCodeTag(sample->vm_tag()); 1314 RegisterProfileCodeTag(sample->vm_tag());
1369 // Make sure user tag exists. 1315 // Make sure user tag exists.
1370 RegisterProfileCodeTag(sample->user_tag()); 1316 RegisterProfileCodeTag(sample->user_tag());
1371 1317
1372 // Make sure that a ProfileCode objects exist for all pcs in the sample 1318 // Make sure that a ProfileCode objects exist for all pcs in the sample
1373 // and tick each one. 1319 // and tick each one.
1374 for (intptr_t frame_index = 0; 1320 for (intptr_t frame_index = 0; frame_index < sample->length();
1375 frame_index < sample->length();
1376 frame_index++) { 1321 frame_index++) {
1377 const uword pc = sample->At(frame_index); 1322 const uword pc = sample->At(frame_index);
1378 ASSERT(pc != 0); 1323 ASSERT(pc != 0);
1379 ProfileCode* code = FindOrRegisterProfileCode(pc, timestamp); 1324 ProfileCode* code = FindOrRegisterProfileCode(pc, timestamp);
1380 ASSERT(code != NULL); 1325 ASSERT(code != NULL);
1381 code->Tick(pc, IsExecutingFrame(sample, frame_index), sample_index); 1326 code->Tick(pc, IsExecutingFrame(sample, frame_index), sample_index);
1382 } 1327 }
1383 1328
1384 TickExitFrame(sample->vm_tag(), sample_index); 1329 TickExitFrame(sample->vm_tag(), sample_index);
1385 } 1330 }
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1454 } else { 1399 } else {
1455 BuildExclusiveCodeTrie(root); 1400 BuildExclusiveCodeTrie(root);
1456 } 1401 }
1457 root->SortChildren(); 1402 root->SortChildren();
1458 profile_->roots_[static_cast<intptr_t>(kind)] = root; 1403 profile_->roots_[static_cast<intptr_t>(kind)] = root;
1459 } 1404 }
1460 1405
1461 void BuildInclusiveCodeTrie(ProfileCodeTrieNode* root) { 1406 void BuildInclusiveCodeTrie(ProfileCodeTrieNode* root) {
1462 ScopeTimer sw("ProfileBuilder::BuildInclusiveCodeTrie", 1407 ScopeTimer sw("ProfileBuilder::BuildInclusiveCodeTrie",
1463 FLAG_trace_profiler); 1408 FLAG_trace_profiler);
1464 for (intptr_t sample_index = 0; 1409 for (intptr_t sample_index = 0; sample_index < samples_->length();
1465 sample_index < samples_->length();
1466 sample_index++) { 1410 sample_index++) {
1467 ProcessedSample* sample = samples_->At(sample_index); 1411 ProcessedSample* sample = samples_->At(sample_index);
1468 1412
1469 // Tick the root. 1413 // Tick the root.
1470 ProfileCodeTrieNode* current = root; 1414 ProfileCodeTrieNode* current = root;
1471 current->Tick(); 1415 current->Tick();
1472 1416
1473 // VM & User tags. 1417 // VM & User tags.
1474 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); 1418 current = AppendTags(sample->vm_tag(), sample->user_tag(), current);
1475 1419
1476 ResetKind(); 1420 ResetKind();
1477 1421
1478 // Truncated tag. 1422 // Truncated tag.
1479 if (sample->truncated()) { 1423 if (sample->truncated()) {
1480 current = AppendTruncatedTag(current); 1424 current = AppendTruncatedTag(current);
1481 } 1425 }
1482 1426
1483 // Walk the sampled PCs. 1427 // Walk the sampled PCs.
1484 Code& code = Code::Handle(); 1428 Code& code = Code::Handle();
1485 for (intptr_t frame_index = sample->length() - 1; 1429 for (intptr_t frame_index = sample->length() - 1; frame_index >= 0;
1486 frame_index >= 0;
1487 frame_index--) { 1430 frame_index--) {
1488 ASSERT(sample->At(frame_index) != 0); 1431 ASSERT(sample->At(frame_index) != 0);
1489 intptr_t index = 1432 intptr_t index =
1490 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); 1433 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp());
1491 ASSERT(index >= 0); 1434 ASSERT(index >= 0);
1492 ProfileCode* profile_code = 1435 ProfileCode* profile_code =
1493 GetProfileCode(sample->At(frame_index), sample->timestamp()); 1436 GetProfileCode(sample->At(frame_index), sample->timestamp());
1494 ASSERT(profile_code->code_table_index() == index); 1437 ASSERT(profile_code->code_table_index() == index);
1495 code ^= profile_code->code(); 1438 code ^= profile_code->code();
1496 current = AppendKind(code, current); 1439 current = AppendKind(code, current);
1497 current = current->GetChild(index); 1440 current = current->GetChild(index);
1498 current->Tick(); 1441 current->Tick();
1499 } 1442 }
1500 1443
1501 if (!sample->first_frame_executing()) { 1444 if (!sample->first_frame_executing()) {
1502 current = AppendExitFrame(sample->vm_tag(), current); 1445 current = AppendExitFrame(sample->vm_tag(), current);
1503 } 1446 }
1504 } 1447 }
1505 } 1448 }
1506 1449
1507 void BuildExclusiveCodeTrie(ProfileCodeTrieNode* root) { 1450 void BuildExclusiveCodeTrie(ProfileCodeTrieNode* root) {
1508 ScopeTimer sw("ProfileBuilder::BuildExclusiveCodeTrie", 1451 ScopeTimer sw("ProfileBuilder::BuildExclusiveCodeTrie",
1509 FLAG_trace_profiler); 1452 FLAG_trace_profiler);
1510 for (intptr_t sample_index = 0; 1453 for (intptr_t sample_index = 0; sample_index < samples_->length();
1511 sample_index < samples_->length();
1512 sample_index++) { 1454 sample_index++) {
1513 ProcessedSample* sample = samples_->At(sample_index); 1455 ProcessedSample* sample = samples_->At(sample_index);
1514 1456
1515 // Tick the root. 1457 // Tick the root.
1516 ProfileCodeTrieNode* current = root; 1458 ProfileCodeTrieNode* current = root;
1517 current->Tick(); 1459 current->Tick();
1518 1460
1519 // VM & User tags. 1461 // VM & User tags.
1520 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); 1462 current = AppendTags(sample->vm_tag(), sample->user_tag(), current);
1521 1463
1522 ResetKind(); 1464 ResetKind();
1523 1465
1524 if (!sample->first_frame_executing()) { 1466 if (!sample->first_frame_executing()) {
1525 current = AppendExitFrame(sample->vm_tag(), current); 1467 current = AppendExitFrame(sample->vm_tag(), current);
1526 } 1468 }
1527 1469
1528 // Walk the sampled PCs. 1470 // Walk the sampled PCs.
1529 Code& code = Code::Handle(); 1471 Code& code = Code::Handle();
1530 for (intptr_t frame_index = 0; 1472 for (intptr_t frame_index = 0; frame_index < sample->length();
1531 frame_index < sample->length();
1532 frame_index++) { 1473 frame_index++) {
1533 ASSERT(sample->At(frame_index) != 0); 1474 ASSERT(sample->At(frame_index) != 0);
1534 intptr_t index = 1475 intptr_t index =
1535 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); 1476 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp());
1536 ASSERT(index >= 0); 1477 ASSERT(index >= 0);
1537 ProfileCode* profile_code = 1478 ProfileCode* profile_code =
1538 GetProfileCode(sample->At(frame_index), sample->timestamp()); 1479 GetProfileCode(sample->At(frame_index), sample->timestamp());
1539 ASSERT(profile_code->code_table_index() == index); 1480 ASSERT(profile_code->code_table_index() == index);
1540 code ^= profile_code->code(); 1481 code ^= profile_code->code();
1541 current = current->GetChild(index); 1482 current = current->GetChild(index);
1542 if (ShouldTickNode(sample, frame_index)) { 1483 if (ShouldTickNode(sample, frame_index)) {
1543 current->Tick(); 1484 current->Tick();
1544 } 1485 }
1545 current = AppendKind(code, current); 1486 current = AppendKind(code, current);
1546 } 1487 }
1547 // Truncated tag. 1488 // Truncated tag.
1548 if (sample->truncated()) { 1489 if (sample->truncated()) {
1549 current = AppendTruncatedTag(current); 1490 current = AppendTruncatedTag(current);
1550 } 1491 }
1551 } 1492 }
1552 } 1493 }
1553 1494
1554 void BuildFunctionTrie(Profile::TrieKind kind) { 1495 void BuildFunctionTrie(Profile::TrieKind kind) {
1555 ProfileFunctionTrieNode* root = 1496 ProfileFunctionTrieNode* root = new ProfileFunctionTrieNode(
1556 new ProfileFunctionTrieNode( 1497 GetProfileFunctionTagIndex(VMTag::kRootTagId));
1557 GetProfileFunctionTagIndex(VMTag::kRootTagId));
1558 // We tick the functions while building the trie, but, we don't want to do 1498 // We tick the functions while building the trie, but, we don't want to do
1559 // it for both tries, just the exclusive trie. 1499 // it for both tries, just the exclusive trie.
1560 inclusive_tree_ = IsInclusiveTrie(kind); 1500 inclusive_tree_ = IsInclusiveTrie(kind);
1561 tick_functions_ = !inclusive_tree_; 1501 tick_functions_ = !inclusive_tree_;
1562 if (inclusive_tree_) { 1502 if (inclusive_tree_) {
1563 BuildInclusiveFunctionTrie(root); 1503 BuildInclusiveFunctionTrie(root);
1564 } else { 1504 } else {
1565 BuildExclusiveFunctionTrie(root); 1505 BuildExclusiveFunctionTrie(root);
1566 } 1506 }
1567 root->SortChildren(); 1507 root->SortChildren();
1568 profile_->roots_[static_cast<intptr_t>(kind)] = root; 1508 profile_->roots_[static_cast<intptr_t>(kind)] = root;
1569 } 1509 }
1570 1510
1571 void BuildInclusiveFunctionTrie(ProfileFunctionTrieNode* root) { 1511 void BuildInclusiveFunctionTrie(ProfileFunctionTrieNode* root) {
1572 ScopeTimer sw("ProfileBuilder::BuildInclusiveFunctionTrie", 1512 ScopeTimer sw("ProfileBuilder::BuildInclusiveFunctionTrie",
1573 FLAG_trace_profiler); 1513 FLAG_trace_profiler);
1574 ASSERT(!tick_functions_); 1514 ASSERT(!tick_functions_);
1575 for (intptr_t sample_index = 0; 1515 for (intptr_t sample_index = 0; sample_index < samples_->length();
1576 sample_index < samples_->length();
1577 sample_index++) { 1516 sample_index++) {
1578 ProcessedSample* sample = samples_->At(sample_index); 1517 ProcessedSample* sample = samples_->At(sample_index);
1579 1518
1580 // Tick the root. 1519 // Tick the root.
1581 ProfileFunctionTrieNode* current = root; 1520 ProfileFunctionTrieNode* current = root;
1582 current->Tick(); 1521 current->Tick();
1583 1522
1584 // VM & User tags. 1523 // VM & User tags.
1585 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); 1524 current = AppendTags(sample->vm_tag(), sample->user_tag(), current);
1586 1525
1587 // Truncated tag. 1526 // Truncated tag.
1588 if (sample->truncated()) { 1527 if (sample->truncated()) {
1589 current = AppendTruncatedTag(current); 1528 current = AppendTruncatedTag(current);
1590 } 1529 }
1591 1530
1592 // Walk the sampled PCs. 1531 // Walk the sampled PCs.
1593 for (intptr_t frame_index = sample->length() - 1; 1532 for (intptr_t frame_index = sample->length() - 1; frame_index >= 0;
1594 frame_index >= 0;
1595 frame_index--) { 1533 frame_index--) {
1596 ASSERT(sample->At(frame_index) != 0); 1534 ASSERT(sample->At(frame_index) != 0);
1597 current = ProcessFrame(current, sample_index, sample, frame_index); 1535 current = ProcessFrame(current, sample_index, sample, frame_index);
1598 } 1536 }
1599 1537
1600 if (!sample->first_frame_executing()) { 1538 if (!sample->first_frame_executing()) {
1601 current = AppendExitFrame(sample->vm_tag(), current); 1539 current = AppendExitFrame(sample->vm_tag(), current);
1602 } 1540 }
1603 1541
1604 sample->set_timeline_trie(current); 1542 sample->set_timeline_trie(current);
1605 } 1543 }
1606 } 1544 }
1607 1545
1608 void BuildExclusiveFunctionTrie(ProfileFunctionTrieNode* root) { 1546 void BuildExclusiveFunctionTrie(ProfileFunctionTrieNode* root) {
1609 ScopeTimer sw("ProfileBuilder::BuildExclusiveFunctionTrie", 1547 ScopeTimer sw("ProfileBuilder::BuildExclusiveFunctionTrie",
1610 FLAG_trace_profiler); 1548 FLAG_trace_profiler);
1611 ASSERT(tick_functions_); 1549 ASSERT(tick_functions_);
1612 for (intptr_t sample_index = 0; 1550 for (intptr_t sample_index = 0; sample_index < samples_->length();
1613 sample_index < samples_->length();
1614 sample_index++) { 1551 sample_index++) {
1615 ProcessedSample* sample = samples_->At(sample_index); 1552 ProcessedSample* sample = samples_->At(sample_index);
1616 1553
1617 // Tick the root. 1554 // Tick the root.
1618 ProfileFunctionTrieNode* current = root; 1555 ProfileFunctionTrieNode* current = root;
1619 current->Tick(); 1556 current->Tick();
1620 1557
1621 // VM & User tags. 1558 // VM & User tags.
1622 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); 1559 current = AppendTags(sample->vm_tag(), sample->user_tag(), current);
1623 1560
1624 ResetKind(); 1561 ResetKind();
1625 1562
1626 if (!sample->first_frame_executing()) { 1563 if (!sample->first_frame_executing()) {
1627 current = AppendExitFrame(sample->vm_tag(), current); 1564 current = AppendExitFrame(sample->vm_tag(), current);
1628 } 1565 }
1629 1566
1630 // Walk the sampled PCs. 1567 // Walk the sampled PCs.
1631 for (intptr_t frame_index = 0; 1568 for (intptr_t frame_index = 0; frame_index < sample->length();
1632 frame_index < sample->length();
1633 frame_index++) { 1569 frame_index++) {
1634 ASSERT(sample->At(frame_index) != 0); 1570 ASSERT(sample->At(frame_index) != 0);
1635 current = ProcessFrame(current, sample_index, sample, frame_index); 1571 current = ProcessFrame(current, sample_index, sample, frame_index);
1636 } 1572 }
1637 1573
1638 TickExitFrameFunction(sample->vm_tag(), sample_index); 1574 TickExitFrameFunction(sample->vm_tag(), sample_index);
1639 1575
1640 // Truncated tag. 1576 // Truncated tag.
1641 if (sample->truncated()) { 1577 if (sample->truncated()) {
1642 current = AppendTruncatedTag(current); 1578 current = AppendTruncatedTag(current);
1643 InclusiveTickTruncatedTag(); 1579 InclusiveTickTruncatedTag();
1644 } 1580 }
1645 } 1581 }
1646 } 1582 }
1647 1583
1648 ProfileFunctionTrieNode* ProcessFrame( 1584 ProfileFunctionTrieNode* ProcessFrame(ProfileFunctionTrieNode* current,
1649 ProfileFunctionTrieNode* current, 1585 intptr_t sample_index,
1650 intptr_t sample_index, 1586 ProcessedSample* sample,
1651 ProcessedSample* sample, 1587 intptr_t frame_index) {
1652 intptr_t frame_index) {
1653 const uword pc = sample->At(frame_index); 1588 const uword pc = sample->At(frame_index);
1654 ProfileCode* profile_code = GetProfileCode(pc, 1589 ProfileCode* profile_code = GetProfileCode(pc, sample->timestamp());
1655 sample->timestamp());
1656 ProfileFunction* function = profile_code->function(); 1590 ProfileFunction* function = profile_code->function();
1657 ASSERT(function != NULL); 1591 ASSERT(function != NULL);
1658 const intptr_t code_index = profile_code->code_table_index(); 1592 const intptr_t code_index = profile_code->code_table_index();
1659 ASSERT(profile_code != NULL); 1593 ASSERT(profile_code != NULL);
1660 const Code& code = Code::ZoneHandle(profile_code->code()); 1594 const Code& code = Code::ZoneHandle(profile_code->code());
1661 GrowableArray<Function*>* inlined_functions = NULL; 1595 GrowableArray<Function*>* inlined_functions = NULL;
1662 GrowableArray<TokenPosition>* inlined_token_positions = NULL; 1596 GrowableArray<TokenPosition>* inlined_token_positions = NULL;
1663 TokenPosition token_position = TokenPosition::kNoSource; 1597 TokenPosition token_position = TokenPosition::kNoSource;
1664 if (!code.IsNull()) { 1598 if (!code.IsNull()) {
1665 inlined_functions_cache_.Get(pc, code, sample, frame_index, 1599 inlined_functions_cache_.Get(pc, code, sample, frame_index,
1666 &inlined_functions, 1600 &inlined_functions, &inlined_token_positions,
1667 &inlined_token_positions,
1668 &token_position); 1601 &token_position);
1669 if (FLAG_trace_profiler_verbose) { 1602 if (FLAG_trace_profiler_verbose) {
1670 for (intptr_t i = 0; i < inlined_functions->length(); i++) { 1603 for (intptr_t i = 0; i < inlined_functions->length(); i++) {
1671 const String& name = 1604 const String& name =
1672 String::Handle((*inlined_functions)[i]->QualifiedScrubbedName()); 1605 String::Handle((*inlined_functions)[i]->QualifiedScrubbedName());
1673 THR_Print("InlinedFunction[%" Pd "] = {%s, %s}\n", 1606 THR_Print("InlinedFunction[%" Pd "] = {%s, %s}\n", i,
1674 i,
1675 name.ToCString(), 1607 name.ToCString(),
1676 (*inlined_token_positions)[i].ToCString()); 1608 (*inlined_token_positions)[i].ToCString());
1677 } 1609 }
1678 } 1610 }
1679 } 1611 }
1680 if (code.IsNull() || 1612 if (code.IsNull() || (inlined_functions == NULL) ||
1681 (inlined_functions == NULL) ||
1682 (inlined_functions->length() == 0)) { 1613 (inlined_functions->length() == 0)) {
1683 // No inlined functions. 1614 // No inlined functions.
1684 if (inclusive_tree_) { 1615 if (inclusive_tree_) {
1685 current = AppendKind(code, current); 1616 current = AppendKind(code, current);
1686 } 1617 }
1687 current = ProcessFunction(current, 1618 current = ProcessFunction(current, sample_index, sample, frame_index,
1688 sample_index, 1619 function, token_position, code_index);
1689 sample,
1690 frame_index,
1691 function,
1692 token_position,
1693 code_index);
1694 if (!inclusive_tree_) { 1620 if (!inclusive_tree_) {
1695 current = AppendKind(code, current); 1621 current = AppendKind(code, current);
1696 } 1622 }
1697 return current; 1623 return current;
1698 } 1624 }
1699 1625
1700 ASSERT(code.is_optimized()); 1626 ASSERT(code.is_optimized());
1701 1627
1702 if (inclusive_tree_) { 1628 if (inclusive_tree_) {
1703 for (intptr_t i = inlined_functions->length() - 1; i >= 0; i--) { 1629 for (intptr_t i = inlined_functions->length() - 1; i >= 0; i--) {
1704 Function* inlined_function = (*inlined_functions)[i]; 1630 Function* inlined_function = (*inlined_functions)[i];
1705 ASSERT(inlined_function != NULL); 1631 ASSERT(inlined_function != NULL);
1706 ASSERT(!inlined_function->IsNull()); 1632 ASSERT(!inlined_function->IsNull());
1707 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; 1633 TokenPosition inlined_token_position = (*inlined_token_positions)[i];
1708 const bool inliner = i == (inlined_functions->length() - 1); 1634 const bool inliner = i == (inlined_functions->length() - 1);
1709 if (inliner) { 1635 if (inliner) {
1710 current = AppendKind(code, current); 1636 current = AppendKind(code, current);
1711 } 1637 }
1712 current = ProcessInlinedFunction(current, 1638 current = ProcessInlinedFunction(current, sample_index, sample,
1713 sample_index, 1639 frame_index, inlined_function,
1714 sample, 1640 inlined_token_position, code_index);
1715 frame_index,
1716 inlined_function,
1717 inlined_token_position,
1718 code_index);
1719 if (inliner) { 1641 if (inliner) {
1720 current = AppendKind(kInlineStart, current); 1642 current = AppendKind(kInlineStart, current);
1721 } 1643 }
1722 } 1644 }
1723 current = AppendKind(kInlineFinish, current); 1645 current = AppendKind(kInlineFinish, current);
1724 } else { 1646 } else {
1725 // Append the inlined children. 1647 // Append the inlined children.
1726 current = AppendKind(kInlineFinish, current); 1648 current = AppendKind(kInlineFinish, current);
1727 for (intptr_t i = 0; i < inlined_functions->length(); i++) { 1649 for (intptr_t i = 0; i < inlined_functions->length(); i++) {
1728 Function* inlined_function = (*inlined_functions)[i]; 1650 Function* inlined_function = (*inlined_functions)[i];
1729 ASSERT(inlined_function != NULL); 1651 ASSERT(inlined_function != NULL);
1730 ASSERT(!inlined_function->IsNull()); 1652 ASSERT(!inlined_function->IsNull());
1731 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; 1653 TokenPosition inlined_token_position = (*inlined_token_positions)[i];
1732 const bool inliner = i == (inlined_functions->length() - 1); 1654 const bool inliner = i == (inlined_functions->length() - 1);
1733 if (inliner) { 1655 if (inliner) {
1734 current = AppendKind(kInlineStart, current); 1656 current = AppendKind(kInlineStart, current);
1735 } 1657 }
1736 current = ProcessInlinedFunction(current, 1658 current = ProcessInlinedFunction(current, sample_index, sample,
1737 sample_index, 1659 frame_index + i, inlined_function,
1738 sample, 1660 inlined_token_position, code_index);
1739 frame_index + i,
1740 inlined_function,
1741 inlined_token_position,
1742 code_index);
1743 if (inliner) { 1661 if (inliner) {
1744 current = AppendKind(code, current); 1662 current = AppendKind(code, current);
1745 } 1663 }
1746 } 1664 }
1747 } 1665 }
1748 1666
1749 return current; 1667 return current;
1750 } 1668 }
1751 1669
1752 ProfileFunctionTrieNode* ProcessInlinedFunction( 1670 ProfileFunctionTrieNode* ProcessInlinedFunction(
1753 ProfileFunctionTrieNode* current, 1671 ProfileFunctionTrieNode* current,
1754 intptr_t sample_index, 1672 intptr_t sample_index,
1755 ProcessedSample* sample, 1673 ProcessedSample* sample,
1756 intptr_t frame_index, 1674 intptr_t frame_index,
1757 Function* inlined_function, 1675 Function* inlined_function,
1758 TokenPosition inlined_token_position, 1676 TokenPosition inlined_token_position,
1759 intptr_t code_index) { 1677 intptr_t code_index) {
1760 ProfileFunctionTable* function_table = profile_->functions_; 1678 ProfileFunctionTable* function_table = profile_->functions_;
1761 ProfileFunction* function = function_table->LookupOrAdd(*inlined_function); 1679 ProfileFunction* function = function_table->LookupOrAdd(*inlined_function);
1762 ASSERT(function != NULL); 1680 ASSERT(function != NULL);
1763 return ProcessFunction(current, 1681 return ProcessFunction(current, sample_index, sample, frame_index, function,
1764 sample_index, 1682 inlined_token_position, code_index);
1765 sample,
1766 frame_index,
1767 function,
1768 inlined_token_position,
1769 code_index);
1770 } 1683 }
1771 1684
1772 bool ShouldTickNode(ProcessedSample* sample, intptr_t frame_index) { 1685 bool ShouldTickNode(ProcessedSample* sample, intptr_t frame_index) {
1773 if (frame_index != 0) { 1686 if (frame_index != 0) {
1774 return true; 1687 return true;
1775 } 1688 }
1776 // Only tick the first frame's node, if we are executing OR 1689 // Only tick the first frame's node, if we are executing OR
1777 // vm tags have been emitted. 1690 // vm tags have been emitted.
1778 return IsExecutingFrame(sample, frame_index) || 1691 return IsExecutingFrame(sample, frame_index) || !FLAG_profile_vm ||
1779 !FLAG_profile_vm || vm_tags_emitted(); 1692 vm_tags_emitted();
1780 } 1693 }
1781 1694
1782 ProfileFunctionTrieNode* ProcessFunction(ProfileFunctionTrieNode* current, 1695 ProfileFunctionTrieNode* ProcessFunction(ProfileFunctionTrieNode* current,
1783 intptr_t sample_index, 1696 intptr_t sample_index,
1784 ProcessedSample* sample, 1697 ProcessedSample* sample,
1785 intptr_t frame_index, 1698 intptr_t frame_index,
1786 ProfileFunction* function, 1699 ProfileFunction* function,
1787 TokenPosition token_position, 1700 TokenPosition token_position,
1788 intptr_t code_index) { 1701 intptr_t code_index) {
1789 if (!function->is_visible()) { 1702 if (!function->is_visible()) {
1790 return current; 1703 return current;
1791 } 1704 }
1792 if (tick_functions_) { 1705 if (tick_functions_) {
1793 if (FLAG_trace_profiler_verbose) { 1706 if (FLAG_trace_profiler_verbose) {
1794 THR_Print("S[%" Pd "]F[%" Pd "] %s %s 0x%" Px "\n", 1707 THR_Print("S[%" Pd "]F[%" Pd "] %s %s 0x%" Px "\n", sample_index,
1795 sample_index, 1708 frame_index, function->Name(), token_position.ToCString(),
1796 frame_index,
1797 function->Name(),
1798 token_position.ToCString(),
1799 sample->At(frame_index)); 1709 sample->At(frame_index));
1800 } 1710 }
1801 function->Tick(IsExecutingFrame(sample, frame_index), 1711 function->Tick(IsExecutingFrame(sample, frame_index), sample_index,
1802 sample_index,
1803 token_position); 1712 token_position);
1804 } 1713 }
1805 function->AddProfileCode(code_index); 1714 function->AddProfileCode(code_index);
1806 current = current->GetChild(function->table_index()); 1715 current = current->GetChild(function->table_index());
1807 if (ShouldTickNode(sample, frame_index)) { 1716 if (ShouldTickNode(sample, frame_index)) {
1808 current->Tick(); 1717 current->Tick();
1809 } 1718 }
1810 current->AddCodeObjectIndex(code_index); 1719 current->AddCodeObjectIndex(code_index);
1811 return current; 1720 return current;
1812 } 1721 }
(...skipping 27 matching lines...) Expand all
1840 1749
1841 ProfileCodeTrieNode* AppendTruncatedTag(ProfileCodeTrieNode* current) { 1750 ProfileCodeTrieNode* AppendTruncatedTag(ProfileCodeTrieNode* current) {
1842 intptr_t truncated_tag_index = 1751 intptr_t truncated_tag_index =
1843 GetProfileCodeTagIndex(VMTag::kTruncatedTagId); 1752 GetProfileCodeTagIndex(VMTag::kTruncatedTagId);
1844 ASSERT(truncated_tag_index >= 0); 1753 ASSERT(truncated_tag_index >= 0);
1845 current = current->GetChild(truncated_tag_index); 1754 current = current->GetChild(truncated_tag_index);
1846 current->Tick(); 1755 current->Tick();
1847 return current; 1756 return current;
1848 } 1757 }
1849 1758
1850 ProfileCodeTrieNode* AppendVMTag(uword vm_tag, 1759 ProfileCodeTrieNode* AppendVMTag(uword vm_tag, ProfileCodeTrieNode* current) {
1851 ProfileCodeTrieNode* current) {
1852 if (VMTag::IsNativeEntryTag(vm_tag)) { 1760 if (VMTag::IsNativeEntryTag(vm_tag)) {
1853 // Insert a dummy kNativeTagId node. 1761 // Insert a dummy kNativeTagId node.
1854 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kNativeTagId); 1762 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kNativeTagId);
1855 current = current->GetChild(tag_index); 1763 current = current->GetChild(tag_index);
1856 // Give the tag a tick. 1764 // Give the tag a tick.
1857 current->Tick(); 1765 current->Tick();
1858 } else if (VMTag::IsRuntimeEntryTag(vm_tag)) { 1766 } else if (VMTag::IsRuntimeEntryTag(vm_tag)) {
1859 // Insert a dummy kRuntimeTagId node. 1767 // Insert a dummy kRuntimeTagId node.
1860 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kRuntimeTagId); 1768 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kRuntimeTagId);
1861 current = current->GetChild(tag_index); 1769 current = current->GetChild(tag_index);
1862 // Give the tag a tick. 1770 // Give the tag a tick.
1863 current->Tick(); 1771 current->Tick();
1864 } else { 1772 } else {
1865 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); 1773 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag);
1866 current = current->GetChild(tag_index); 1774 current = current->GetChild(tag_index);
1867 // Give the tag a tick. 1775 // Give the tag a tick.
1868 current->Tick(); 1776 current->Tick();
1869 } 1777 }
1870 return current; 1778 return current;
1871 } 1779 }
1872 1780
1873 ProfileCodeTrieNode* AppendSpecificNativeRuntimeEntryVMTag( 1781 ProfileCodeTrieNode* AppendSpecificNativeRuntimeEntryVMTag(
1874 uword vm_tag, ProfileCodeTrieNode* current) { 1782 uword vm_tag,
1783 ProfileCodeTrieNode* current) {
1875 // Only Native and Runtime entries have a second VM tag. 1784 // Only Native and Runtime entries have a second VM tag.
1876 if (!VMTag::IsNativeEntryTag(vm_tag) && 1785 if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) {
1877 !VMTag::IsRuntimeEntryTag(vm_tag)) {
1878 return current; 1786 return current;
1879 } 1787 }
1880 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); 1788 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag);
1881 current = current->GetChild(tag_index); 1789 current = current->GetChild(tag_index);
1882 // Give the tag a tick. 1790 // Give the tag a tick.
1883 current->Tick(); 1791 current->Tick();
1884 return current; 1792 return current;
1885 } 1793 }
1886 1794
1887 uword ProfileInfoKindToVMTag(ProfileInfoKind kind) { 1795 uword ProfileInfoKindToVMTag(ProfileInfoKind kind) {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1969 ProfileCodeTrieNode* AppendExitFrame(uword vm_tag, 1877 ProfileCodeTrieNode* AppendExitFrame(uword vm_tag,
1970 ProfileCodeTrieNode* current) { 1878 ProfileCodeTrieNode* current) {
1971 if (FLAG_profile_vm) { 1879 if (FLAG_profile_vm) {
1972 return current; 1880 return current;
1973 } 1881 }
1974 1882
1975 if (!VMTag::IsExitFrameTag(vm_tag)) { 1883 if (!VMTag::IsExitFrameTag(vm_tag)) {
1976 return current; 1884 return current;
1977 } 1885 }
1978 1886
1979 if (VMTag::IsNativeEntryTag(vm_tag) || 1887 if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) {
1980 VMTag::IsRuntimeEntryTag(vm_tag)) {
1981 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); 1888 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current);
1982 } else { 1889 } else {
1983 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); 1890 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag);
1984 current = current->GetChild(tag_index); 1891 current = current->GetChild(tag_index);
1985 // Give the tag a tick. 1892 // Give the tag a tick.
1986 current->Tick(); 1893 current->Tick();
1987 } 1894 }
1988 return current; 1895 return current;
1989 } 1896 }
1990 1897
(...skipping 27 matching lines...) Expand all
2018 } 1925 }
2019 1926
2020 if (tag_order() == Profile::kNoTags) { 1927 if (tag_order() == Profile::kNoTags) {
2021 return current; 1928 return current;
2022 } 1929 }
2023 1930
2024 return AppendUserTag(user_tag, current); 1931 return AppendUserTag(user_tag, current);
2025 } 1932 }
2026 1933
2027 // ProfileFunctionTrieNode 1934 // ProfileFunctionTrieNode
2028 void ResetKind() { 1935 void ResetKind() { info_kind_ = kNone; }
2029 info_kind_ = kNone;
2030 }
2031 1936
2032 ProfileFunctionTrieNode* AppendKind(ProfileInfoKind kind, 1937 ProfileFunctionTrieNode* AppendKind(ProfileInfoKind kind,
2033 ProfileFunctionTrieNode* current) { 1938 ProfileFunctionTrieNode* current) {
2034 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { 1939 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) {
2035 // Only emit if debug tags are requested. 1940 // Only emit if debug tags are requested.
2036 return current; 1941 return current;
2037 } 1942 }
2038 if (kind != info_kind_) { 1943 if (kind != info_kind_) {
2039 info_kind_ = kind; 1944 info_kind_ = kind;
2040 intptr_t tag_index = 1945 intptr_t tag_index =
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2094 } else { 1999 } else {
2095 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); 2000 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag);
2096 current = current->GetChild(tag_index); 2001 current = current->GetChild(tag_index);
2097 // Give the tag a tick. 2002 // Give the tag a tick.
2098 current->Tick(); 2003 current->Tick();
2099 } 2004 }
2100 return current; 2005 return current;
2101 } 2006 }
2102 2007
2103 ProfileFunctionTrieNode* AppendSpecificNativeRuntimeEntryVMTag( 2008 ProfileFunctionTrieNode* AppendSpecificNativeRuntimeEntryVMTag(
2104 uword vm_tag, ProfileFunctionTrieNode* current) { 2009 uword vm_tag,
2010 ProfileFunctionTrieNode* current) {
2105 // Only Native and Runtime entries have a second VM tag. 2011 // Only Native and Runtime entries have a second VM tag.
2106 if (!VMTag::IsNativeEntryTag(vm_tag) && 2012 if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) {
2107 !VMTag::IsRuntimeEntryTag(vm_tag)) {
2108 return current; 2013 return current;
2109 } 2014 }
2110 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); 2015 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag);
2111 current = current->GetChild(tag_index); 2016 current = current->GetChild(tag_index);
2112 // Give the tag a tick. 2017 // Give the tag a tick.
2113 current->Tick(); 2018 current->Tick();
2114 return current; 2019 return current;
2115 } 2020 }
2116 2021
2117 ProfileFunctionTrieNode* AppendVMTags(uword vm_tag, 2022 ProfileFunctionTrieNode* AppendVMTags(uword vm_tag,
2118 ProfileFunctionTrieNode* current) { 2023 ProfileFunctionTrieNode* current) {
2119 current = AppendVMTag(vm_tag, current); 2024 current = AppendVMTag(vm_tag, current);
2120 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); 2025 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current);
2121 return current; 2026 return current;
2122 } 2027 }
2123 2028
2124 ProfileFunctionTrieNode* AppendExitFrame(uword vm_tag, 2029 ProfileFunctionTrieNode* AppendExitFrame(uword vm_tag,
2125 ProfileFunctionTrieNode* current) { 2030 ProfileFunctionTrieNode* current) {
2126 if (FLAG_profile_vm) { 2031 if (FLAG_profile_vm) {
2127 return current; 2032 return current;
2128 } 2033 }
2129 2034
2130 if (!VMTag::IsExitFrameTag(vm_tag)) { 2035 if (!VMTag::IsExitFrameTag(vm_tag)) {
2131 return current; 2036 return current;
2132 } 2037 }
2133 if (VMTag::IsNativeEntryTag(vm_tag) || 2038 if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) {
2134 VMTag::IsRuntimeEntryTag(vm_tag)) {
2135 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); 2039 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current);
2136 } else { 2040 } else {
2137 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); 2041 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag);
2138 current = current->GetChild(tag_index); 2042 current = current->GetChild(tag_index);
2139 // Give the tag a tick. 2043 // Give the tag a tick.
2140 current->Tick(); 2044 current->Tick();
2141 } 2045 }
2142 return current; 2046 return current;
2143 } 2047 }
2144 2048
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2233 if (tag == 0) { 2137 if (tag == 0) {
2234 // No tag. 2138 // No tag.
2235 return; 2139 return;
2236 } 2140 }
2237 ProfileCodeTable* tag_table = profile_->tag_code_; 2141 ProfileCodeTable* tag_table = profile_->tag_code_;
2238 intptr_t index = tag_table->FindCodeIndexForPC(tag); 2142 intptr_t index = tag_table->FindCodeIndexForPC(tag);
2239 if (index >= 0) { 2143 if (index >= 0) {
2240 // Already created. 2144 // Already created.
2241 return; 2145 return;
2242 } 2146 }
2243 ProfileCode* code = new ProfileCode(ProfileCode::kTagCode, 2147 ProfileCode* code =
2244 tag, 2148 new ProfileCode(ProfileCode::kTagCode, tag, tag + 1, 0, null_code_);
2245 tag + 1,
2246 0,
2247 null_code_);
2248 index = tag_table->InsertCode(code); 2149 index = tag_table->InsertCode(code);
2249 ASSERT(index >= 0); 2150 ASSERT(index >= 0);
2250 } 2151 }
2251 2152
2252 ProfileCode* CreateProfileCodeReused(uword pc) { 2153 ProfileCode* CreateProfileCodeReused(uword pc) {
2253 ProfileCode* code = new ProfileCode(ProfileCode::kReusedCode, 2154 ProfileCode* code =
2254 pc, 2155 new ProfileCode(ProfileCode::kReusedCode, pc, pc + 1, 0, null_code_);
2255 pc + 1,
2256 0,
2257 null_code_);
2258 return code; 2156 return code;
2259 } 2157 }
2260 2158
2261 bool IsPCInDartHeap(uword pc) { 2159 bool IsPCInDartHeap(uword pc) {
2262 return vm_isolate_->heap()->CodeContains(pc) || 2160 return vm_isolate_->heap()->CodeContains(pc) ||
2263 thread_->isolate()->heap()->CodeContains(pc); 2161 thread_->isolate()->heap()->CodeContains(pc);
2264 } 2162 }
2265 2163
2266 2164
2267 ProfileCode* FindOrRegisterNativeProfileCode(uword pc) { 2165 ProfileCode* FindOrRegisterNativeProfileCode(uword pc) {
2268 // Check if |pc| is already known in the live code table. 2166 // Check if |pc| is already known in the live code table.
2269 ProfileCodeTable* live_table = profile_->live_code_; 2167 ProfileCodeTable* live_table = profile_->live_code_;
2270 ProfileCode* profile_code = live_table->FindCodeForPC(pc); 2168 ProfileCode* profile_code = live_table->FindCodeForPC(pc);
2271 if (profile_code != NULL) { 2169 if (profile_code != NULL) {
2272 return profile_code; 2170 return profile_code;
2273 } 2171 }
2274 2172
2275 // We haven't seen this pc yet. 2173 // We haven't seen this pc yet.
2276 Code& code = Code::Handle(thread_->zone()); 2174 Code& code = Code::Handle(thread_->zone());
2277 2175
2278 // Check NativeSymbolResolver for pc. 2176 // Check NativeSymbolResolver for pc.
2279 uintptr_t native_start = 0; 2177 uintptr_t native_start = 0;
2280 char* native_name = NativeSymbolResolver::LookupSymbolName(pc, 2178 char* native_name =
2281 &native_start); 2179 NativeSymbolResolver::LookupSymbolName(pc, &native_start);
2282 if (native_name == NULL) { 2180 if (native_name == NULL) {
2283 // Failed to find a native symbol for pc. 2181 // Failed to find a native symbol for pc.
2284 native_start = pc; 2182 native_start = pc;
2285 } 2183 }
2286 2184
2287 #if defined(HOST_ARCH_ARM) 2185 #if defined(HOST_ARCH_ARM)
2288 // The symbol for a Thumb function will be xxx1, but we may have samples 2186 // The symbol for a Thumb function will be xxx1, but we may have samples
2289 // at function entry which will have pc xxx0. 2187 // at function entry which will have pc xxx0.
2290 native_start &= ~1; 2188 native_start &= ~1;
2291 #endif 2189 #endif
2292 2190
2293 ASSERT(pc >= native_start); 2191 ASSERT(pc >= native_start);
2294 profile_code = new ProfileCode(ProfileCode::kNativeCode, 2192 profile_code = new ProfileCode(ProfileCode::kNativeCode, native_start,
2295 native_start, 2193 pc + 1, 0, code);
2296 pc + 1,
2297 0,
2298 code);
2299 if (native_name != NULL) { 2194 if (native_name != NULL) {
2300 profile_code->SetName(native_name); 2195 profile_code->SetName(native_name);
2301 NativeSymbolResolver::FreeSymbolName(native_name); 2196 NativeSymbolResolver::FreeSymbolName(native_name);
2302 } 2197 }
2303 2198
2304 RegisterLiveProfileCode(profile_code); 2199 RegisterLiveProfileCode(profile_code);
2305 return profile_code; 2200 return profile_code;
2306 } 2201 }
2307 2202
2308 void RegisterLiveProfileCode(ProfileCode* code) { 2203 void RegisterLiveProfileCode(ProfileCode* code) {
(...skipping 24 matching lines...) Expand all
2333 return code; 2228 return code;
2334 } 2229 }
2335 if ((code == NULL) && !IsPCInDartHeap(pc)) { 2230 if ((code == NULL) && !IsPCInDartHeap(pc)) {
2336 // Not a PC from Dart code. Check with native code. 2231 // Not a PC from Dart code. Check with native code.
2337 return FindOrRegisterNativeProfileCode(pc); 2232 return FindOrRegisterNativeProfileCode(pc);
2338 } 2233 }
2339 // We either didn't find the code or it was compiled after the sample. 2234 // We either didn't find the code or it was compiled after the sample.
2340 return FindOrRegisterDeadProfileCode(pc); 2235 return FindOrRegisterDeadProfileCode(pc);
2341 } 2236 }
2342 2237
2343 Profile::TagOrder tag_order() const { 2238 Profile::TagOrder tag_order() const { return tag_order_; }
2344 return tag_order_;
2345 }
2346 2239
2347 bool vm_tags_emitted() const { 2240 bool vm_tags_emitted() const {
2348 return (tag_order_ == Profile::kUserVM) || 2241 return (tag_order_ == Profile::kUserVM) ||
2349 (tag_order_ == Profile::kVMUser) || 2242 (tag_order_ == Profile::kVMUser) || (tag_order_ == Profile::kVM);
2350 (tag_order_ == Profile::kVM);
2351 } 2243 }
2352 2244
2353 bool TagsEnabled(intptr_t extra_tags_bits) const { 2245 bool TagsEnabled(intptr_t extra_tags_bits) const {
2354 return (extra_tags_ & extra_tags_bits) != 0; 2246 return (extra_tags_ & extra_tags_bits) != 0;
2355 } 2247 }
2356 2248
2357 Thread* thread_; 2249 Thread* thread_;
2358 Isolate* vm_isolate_; 2250 Isolate* vm_isolate_;
2359 SampleFilter* filter_; 2251 SampleFilter* filter_;
2360 Profile::TagOrder tag_order_; 2252 Profile::TagOrder tag_order_;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
2434 return tag_code_->At(index); 2326 return tag_code_->At(index);
2435 } 2327 }
2436 2328
2437 2329
2438 ProfileTrieNode* Profile::GetTrieRoot(TrieKind trie_kind) { 2330 ProfileTrieNode* Profile::GetTrieRoot(TrieKind trie_kind) {
2439 return roots_[static_cast<intptr_t>(trie_kind)]; 2331 return roots_[static_cast<intptr_t>(trie_kind)];
2440 } 2332 }
2441 2333
2442 2334
2443 void Profile::PrintHeaderJSON(JSONObject* obj) { 2335 void Profile::PrintHeaderJSON(JSONObject* obj) {
2444 obj->AddProperty("samplePeriod", 2336 obj->AddProperty("samplePeriod", static_cast<intptr_t>(FLAG_profile_period));
2445 static_cast<intptr_t>(FLAG_profile_period)); 2337 obj->AddProperty("stackDepth", static_cast<intptr_t>(FLAG_max_profile_depth));
2446 obj->AddProperty("stackDepth",
2447 static_cast<intptr_t>(FLAG_max_profile_depth));
2448 obj->AddProperty("sampleCount", sample_count()); 2338 obj->AddProperty("sampleCount", sample_count());
2449 obj->AddProperty("timeSpan", MicrosecondsToSeconds(GetTimeSpan())); 2339 obj->AddProperty("timeSpan", MicrosecondsToSeconds(GetTimeSpan()));
2450 obj->AddPropertyTimeMicros("timeOriginMicros", min_time()); 2340 obj->AddPropertyTimeMicros("timeOriginMicros", min_time());
2451 obj->AddPropertyTimeMicros("timeExtentMicros", GetTimeSpan()); 2341 obj->AddPropertyTimeMicros("timeExtentMicros", GetTimeSpan());
2452 2342
2453 ProfilerCounters counters = Profiler::counters(); 2343 ProfilerCounters counters = Profiler::counters();
2454 { 2344 {
2455 JSONObject counts(obj, "counters"); 2345 JSONObject counts(obj, "counters");
2456 counts.AddProperty64( 2346 counts.AddProperty64("bail_out_unknown_task",
2457 "bail_out_unknown_task", 2347 counters.bail_out_unknown_task);
2458 counters.bail_out_unknown_task); 2348 counts.AddProperty64("bail_out_jump_to_exception_handler",
2459 counts.AddProperty64( 2349 counters.bail_out_jump_to_exception_handler);
2460 "bail_out_jump_to_exception_handler", 2350 counts.AddProperty64("bail_out_check_isolate",
2461 counters.bail_out_jump_to_exception_handler); 2351 counters.bail_out_check_isolate);
2462 counts.AddProperty64( 2352 counts.AddProperty64("single_frame_sample_deoptimizing",
2463 "bail_out_check_isolate", 2353 counters.single_frame_sample_deoptimizing);
2464 counters.bail_out_check_isolate); 2354 counts.AddProperty64("single_frame_sample_register_check",
2465 counts.AddProperty64( 2355 counters.single_frame_sample_register_check);
2466 "single_frame_sample_deoptimizing",
2467 counters.single_frame_sample_deoptimizing);
2468 counts.AddProperty64(
2469 "single_frame_sample_register_check",
2470 counters.single_frame_sample_register_check);
2471 counts.AddProperty64( 2356 counts.AddProperty64(
2472 "single_frame_sample_get_and_validate_stack_bounds", 2357 "single_frame_sample_get_and_validate_stack_bounds",
2473 counters.single_frame_sample_get_and_validate_stack_bounds); 2358 counters.single_frame_sample_get_and_validate_stack_bounds);
2474 counts.AddProperty64( 2359 counts.AddProperty64("stack_walker_native", counters.stack_walker_native);
2475 "stack_walker_native", 2360 counts.AddProperty64("stack_walker_dart_exit",
2476 counters.stack_walker_native); 2361 counters.stack_walker_dart_exit);
2477 counts.AddProperty64( 2362 counts.AddProperty64("stack_walker_dart", counters.stack_walker_dart);
2478 "stack_walker_dart_exit", 2363 counts.AddProperty64("stack_walker_none", counters.stack_walker_none);
2479 counters.stack_walker_dart_exit);
2480 counts.AddProperty64(
2481 "stack_walker_dart",
2482 counters.stack_walker_dart);
2483 counts.AddProperty64(
2484 "stack_walker_none",
2485 counters.stack_walker_none);
2486 } 2364 }
2487 } 2365 }
2488 2366
2489 2367
2490 void Profile::PrintTimelineFrameJSON(JSONObject* frames, 2368 void Profile::PrintTimelineFrameJSON(JSONObject* frames,
2491 ProfileTrieNode* current, 2369 ProfileTrieNode* current,
2492 ProfileTrieNode* parent, 2370 ProfileTrieNode* parent,
2493 intptr_t* next_id) { 2371 intptr_t* next_id) {
2494 ASSERT(current->frame_id() == -1); 2372 ASSERT(current->frame_id() == -1);
2495 const intptr_t id = *next_id; 2373 const intptr_t id = *next_id;
2496 *next_id = id + 1; 2374 *next_id = id + 1;
2497 current->set_frame_id(id); 2375 current->set_frame_id(id);
2498 ASSERT(current->frame_id() != -1); 2376 ASSERT(current->frame_id() != -1);
2499 2377
2500 { 2378 {
2501 // The samples from many isolates may be merged into a single timeline, 2379 // The samples from many isolates may be merged into a single timeline,
2502 // so prefix frames id with the isolate. 2380 // so prefix frames id with the isolate.
2503 intptr_t isolate_id = reinterpret_cast<intptr_t>(isolate_); 2381 intptr_t isolate_id = reinterpret_cast<intptr_t>(isolate_);
2504 const char* key = zone_->PrintToString("%" Pd "-%" Pd, 2382 const char* key =
2505 isolate_id, current->frame_id()); 2383 zone_->PrintToString("%" Pd "-%" Pd, isolate_id, current->frame_id());
2506 JSONObject frame(frames, key); 2384 JSONObject frame(frames, key);
2507 frame.AddProperty("category", "Dart"); 2385 frame.AddProperty("category", "Dart");
2508 ProfileFunction* func = GetFunction(current->table_index()); 2386 ProfileFunction* func = GetFunction(current->table_index());
2509 frame.AddProperty("name", func->Name()); 2387 frame.AddProperty("name", func->Name());
2510 if (parent != NULL) { 2388 if (parent != NULL) {
2511 ASSERT(parent->frame_id() != -1); 2389 ASSERT(parent->frame_id() != -1);
2512 frame.AddPropertyF("parent", "%" Pd "-%" Pd, 2390 frame.AddPropertyF("parent", "%" Pd "-%" Pd, isolate_id,
2513 isolate_id, parent->frame_id()); 2391 parent->frame_id());
2514 } 2392 }
2515 } 2393 }
2516 2394
2517 for (intptr_t i = 0; i < current->NumChildren(); i++) { 2395 for (intptr_t i = 0; i < current->NumChildren(); i++) {
2518 ProfileTrieNode* child = current->At(i); 2396 ProfileTrieNode* child = current->At(i);
2519 PrintTimelineFrameJSON(frames, child, current, next_id); 2397 PrintTimelineFrameJSON(frames, child, current, next_id);
2520 } 2398 }
2521 } 2399 }
2522 2400
2523 2401
2524 void Profile::PrintTimelineJSON(JSONStream* stream) { 2402 void Profile::PrintTimelineJSON(JSONStream* stream) {
2525 ScopeTimer sw("Profile::PrintTimelineJSON", FLAG_trace_profiler); 2403 ScopeTimer sw("Profile::PrintTimelineJSON", FLAG_trace_profiler);
2526 JSONObject obj(stream); 2404 JSONObject obj(stream);
2527 obj.AddProperty("type", "_CpuProfileTimeline"); 2405 obj.AddProperty("type", "_CpuProfileTimeline");
2528 PrintHeaderJSON(&obj); 2406 PrintHeaderJSON(&obj);
2529 { 2407 {
2530 JSONObject frames(&obj, "stackFrames"); 2408 JSONObject frames(&obj, "stackFrames");
2531 ProfileTrieNode* root = GetTrieRoot(kInclusiveFunction); 2409 ProfileTrieNode* root = GetTrieRoot(kInclusiveFunction);
2532 intptr_t next_id = 0; 2410 intptr_t next_id = 0;
2533 PrintTimelineFrameJSON(&frames, root, NULL, &next_id); 2411 PrintTimelineFrameJSON(&frames, root, NULL, &next_id);
2534 } 2412 }
2535 { 2413 {
2536 JSONArray events(&obj, "traceEvents"); 2414 JSONArray events(&obj, "traceEvents");
2537 intptr_t pid = OS::ProcessId(); 2415 intptr_t pid = OS::ProcessId();
2538 intptr_t isolate_id = reinterpret_cast<intptr_t>(isolate_); 2416 intptr_t isolate_id = reinterpret_cast<intptr_t>(isolate_);
2539 for (intptr_t sample_index = 0; 2417 for (intptr_t sample_index = 0; sample_index < samples_->length();
2540 sample_index < samples_->length();
2541 sample_index++) { 2418 sample_index++) {
2542 ProcessedSample* sample = samples_->At(sample_index); 2419 ProcessedSample* sample = samples_->At(sample_index);
2543 JSONObject event(&events); 2420 JSONObject event(&events);
2544 event.AddProperty("ph", "P"); // kind = sample event 2421 event.AddProperty("ph", "P"); // kind = sample event
2545 event.AddProperty64("pid", pid); 2422 event.AddProperty64("pid", pid);
2546 event.AddProperty64("tid", OSThread::ThreadIdToIntPtr(sample->tid())); 2423 event.AddProperty64("tid", OSThread::ThreadIdToIntPtr(sample->tid()));
2547 event.AddPropertyTimeMicros("ts", sample->timestamp()); 2424 event.AddPropertyTimeMicros("ts", sample->timestamp());
2548 event.AddProperty("cat", "Dart"); 2425 event.AddProperty("cat", "Dart");
2549 2426
2550 ProfileTrieNode* trie = sample->timeline_trie(); 2427 ProfileTrieNode* trie = sample->timeline_trie();
2551 ASSERT(trie->frame_id() != -1); 2428 ASSERT(trie->frame_id() != -1);
2552 event.AddPropertyF("sf", "%" Pd "-%" Pd, 2429 event.AddPropertyF("sf", "%" Pd "-%" Pd, isolate_id, trie->frame_id());
2553 isolate_id, trie->frame_id());
2554 } 2430 }
2555 } 2431 }
2556 } 2432 }
2557 2433
2558 2434
2559 ProfileFunction* Profile::FindFunction(const Function& function) { 2435 ProfileFunction* Profile::FindFunction(const Function& function) {
2560 return (functions_ != NULL) ? functions_->Lookup(function) : NULL; 2436 return (functions_ != NULL) ? functions_->Lookup(function) : NULL;
2561 } 2437 }
2562 2438
2563 2439
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
2794 2670
2795 class NoAllocationSampleFilter : public SampleFilter { 2671 class NoAllocationSampleFilter : public SampleFilter {
2796 public: 2672 public:
2797 NoAllocationSampleFilter(Isolate* isolate, 2673 NoAllocationSampleFilter(Isolate* isolate,
2798 intptr_t thread_task_mask, 2674 intptr_t thread_task_mask,
2799 int64_t time_origin_micros, 2675 int64_t time_origin_micros,
2800 int64_t time_extent_micros) 2676 int64_t time_extent_micros)
2801 : SampleFilter(isolate, 2677 : SampleFilter(isolate,
2802 thread_task_mask, 2678 thread_task_mask,
2803 time_origin_micros, 2679 time_origin_micros,
2804 time_extent_micros) { 2680 time_extent_micros) {}
2805 }
2806 2681
2807 bool FilterSample(Sample* sample) { 2682 bool FilterSample(Sample* sample) { return !sample->is_allocation_sample(); }
2808 return !sample->is_allocation_sample();
2809 }
2810 }; 2683 };
2811 2684
2812 2685
2813 void ProfilerService::PrintJSON(JSONStream* stream, 2686 void ProfilerService::PrintJSON(JSONStream* stream,
2814 Profile::TagOrder tag_order, 2687 Profile::TagOrder tag_order,
2815 intptr_t extra_tags, 2688 intptr_t extra_tags,
2816 int64_t time_origin_micros, 2689 int64_t time_origin_micros,
2817 int64_t time_extent_micros) { 2690 int64_t time_extent_micros) {
2818 Thread* thread = Thread::Current(); 2691 Thread* thread = Thread::Current();
2819 Isolate* isolate = thread->isolate(); 2692 Isolate* isolate = thread->isolate();
2820 NoAllocationSampleFilter filter(isolate, 2693 NoAllocationSampleFilter filter(isolate, Thread::kMutatorTask,
2821 Thread::kMutatorTask, 2694 time_origin_micros, time_extent_micros);
2822 time_origin_micros,
2823 time_extent_micros);
2824 const bool as_timeline = false; 2695 const bool as_timeline = false;
2825 PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter, as_timeline); 2696 PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter, as_timeline);
2826 } 2697 }
2827 2698
2828 2699
2829 class ClassAllocationSampleFilter : public SampleFilter { 2700 class ClassAllocationSampleFilter : public SampleFilter {
2830 public: 2701 public:
2831 ClassAllocationSampleFilter(Isolate* isolate, 2702 ClassAllocationSampleFilter(Isolate* isolate,
2832 const Class& cls, 2703 const Class& cls,
2833 intptr_t thread_task_mask, 2704 intptr_t thread_task_mask,
(...skipping 17 matching lines...) Expand all
2851 }; 2722 };
2852 2723
2853 2724
2854 void ProfilerService::PrintAllocationJSON(JSONStream* stream, 2725 void ProfilerService::PrintAllocationJSON(JSONStream* stream,
2855 Profile::TagOrder tag_order, 2726 Profile::TagOrder tag_order,
2856 const Class& cls, 2727 const Class& cls,
2857 int64_t time_origin_micros, 2728 int64_t time_origin_micros,
2858 int64_t time_extent_micros) { 2729 int64_t time_extent_micros) {
2859 Thread* thread = Thread::Current(); 2730 Thread* thread = Thread::Current();
2860 Isolate* isolate = thread->isolate(); 2731 Isolate* isolate = thread->isolate();
2861 ClassAllocationSampleFilter filter(isolate, 2732 ClassAllocationSampleFilter filter(isolate, cls, Thread::kMutatorTask,
2862 cls, 2733 time_origin_micros, time_extent_micros);
2863 Thread::kMutatorTask,
2864 time_origin_micros,
2865 time_extent_micros);
2866 const bool as_timeline = false; 2734 const bool as_timeline = false;
2867 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); 2735 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline);
2868 } 2736 }
2869 2737
2870 2738
2871 void ProfilerService::PrintTimelineJSON(JSONStream* stream, 2739 void ProfilerService::PrintTimelineJSON(JSONStream* stream,
2872 Profile::TagOrder tag_order, 2740 Profile::TagOrder tag_order,
2873 int64_t time_origin_micros, 2741 int64_t time_origin_micros,
2874 int64_t time_extent_micros) { 2742 int64_t time_extent_micros) {
2875 Thread* thread = Thread::Current(); 2743 Thread* thread = Thread::Current();
2876 Isolate* isolate = thread->isolate(); 2744 Isolate* isolate = thread->isolate();
2877 const intptr_t thread_task_mask = Thread::kMutatorTask | 2745 const intptr_t thread_task_mask = Thread::kMutatorTask |
2878 Thread::kCompilerTask | 2746 Thread::kCompilerTask |
2879 Thread::kSweeperTask | 2747 Thread::kSweeperTask | Thread::kMarkerTask;
2880 Thread::kMarkerTask; 2748 NoAllocationSampleFilter filter(isolate, thread_task_mask, time_origin_micros,
2881 NoAllocationSampleFilter filter(isolate,
2882 thread_task_mask,
2883 time_origin_micros,
2884 time_extent_micros); 2749 time_extent_micros);
2885 const bool as_timeline = true; 2750 const bool as_timeline = true;
2886 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); 2751 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline);
2887 } 2752 }
2888 2753
2889 2754
2890 void ProfilerService::ClearSamples() { 2755 void ProfilerService::ClearSamples() {
2891 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 2756 SampleBuffer* sample_buffer = Profiler::sample_buffer();
2892 if (sample_buffer == NULL) { 2757 if (sample_buffer == NULL) {
2893 return; 2758 return;
2894 } 2759 }
2895 2760
2896 Thread* thread = Thread::Current(); 2761 Thread* thread = Thread::Current();
2897 Isolate* isolate = thread->isolate(); 2762 Isolate* isolate = thread->isolate();
2898 2763
2899 // Disable thread interrupts while processing the buffer. 2764 // Disable thread interrupts while processing the buffer.
2900 DisableThreadInterruptsScope dtis(thread); 2765 DisableThreadInterruptsScope dtis(thread);
2901 2766
2902 ClearProfileVisitor clear_profile(isolate); 2767 ClearProfileVisitor clear_profile(isolate);
2903 sample_buffer->VisitSamples(&clear_profile); 2768 sample_buffer->VisitSamples(&clear_profile);
2904 } 2769 }
2905 2770
2906 #endif // !PRODUCT 2771 #endif // !PRODUCT
2907 2772
2908 } // namespace dart 2773 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/profiler_service.h ('k') | runtime/vm/profiler_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698