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

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

Issue 1202943002: Begin transition to ProcessedSample in Profiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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
« runtime/vm/profiler.h ('K') | « runtime/vm/profiler.cc ('k') | no next file » | 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/native_symbol.h" 8 #include "vm/native_symbol.h"
9 #include "vm/object.h" 9 #include "vm/object.h"
10 #include "vm/os.h" 10 #include "vm/os.h"
11 #include "vm/profiler.h" 11 #include "vm/profiler.h"
12 #include "vm/reusable_handles.h" 12 #include "vm/reusable_handles.h"
13 #include "vm/scope_timer.h" 13 #include "vm/scope_timer.h"
14 14
15 namespace dart { 15 namespace dart {
16 16
17 DECLARE_FLAG(int, profile_depth); 17 DECLARE_FLAG(int, profile_depth);
18 DECLARE_FLAG(int, profile_period); 18 DECLARE_FLAG(int, profile_period);
19 19
20 DEFINE_FLAG(bool, trace_profiler, false, "Trace profiler."); 20 DEFINE_FLAG(bool, trace_profiler, true, "Trace profiler.");
rmacnak 2015/06/23 22:38:54 Revert to false.
Cutch 2015/06/24 13:54:34 Done.
21 21
22 // Forward declarations. 22 // Forward declarations.
23 class CodeRegion; 23 class CodeRegion;
24 class ProfileFunction; 24 class ProfileFunction;
25 class ProfileFunctionTable; 25 class ProfileFunctionTable;
26 26
27 27
28 class DeoptimizedCodeSet : public ZoneAllocated { 28 class DeoptimizedCodeSet : public ZoneAllocated {
29 public: 29 public:
30 explicit DeoptimizedCodeSet(Isolate* isolate) 30 explicit DeoptimizedCodeSet(Isolate* isolate)
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 int64_t timestamp, 377 int64_t timestamp,
378 const Code& code) 378 const Code& code)
379 : kind_(kind), 379 : kind_(kind),
380 start_(start), 380 start_(start),
381 end_(end), 381 end_(end),
382 inclusive_ticks_(0), 382 inclusive_ticks_(0),
383 exclusive_ticks_(0), 383 exclusive_ticks_(0),
384 inclusive_tick_serial_(0), 384 inclusive_tick_serial_(0),
385 name_(NULL), 385 name_(NULL),
386 compile_timestamp_(timestamp), 386 compile_timestamp_(timestamp),
387 creation_serial_(0),
388 code_(Code::ZoneHandle(code.raw())), 387 code_(Code::ZoneHandle(code.raw())),
389 profile_function_(NULL), 388 profile_function_(NULL),
390 code_table_index_(-1) { 389 code_table_index_(-1) {
391 ASSERT(start_ < end_); 390 ASSERT(start_ < end_);
392 // Ensure all kDartCode have a valid code_ object. 391 // Ensure all kDartCode have a valid code_ object.
393 ASSERT((kind != kDartCode) || (!code_.IsNull())); 392 ASSERT((kind != kDartCode) || (!code_.IsNull()));
394 } 393 }
395 394
396 uword start() const { return start_; } 395 uword start() const { return start_; }
397 void set_start(uword start) { 396 void set_start(uword start) {
(...skipping 20 matching lines...) Expand all
418 } 417 }
419 418
420 bool overlaps(const CodeRegion* other) const { 419 bool overlaps(const CodeRegion* other) const {
421 ASSERT(other != NULL); 420 ASSERT(other != NULL);
422 return other->contains(start_) || 421 return other->contains(start_) ||
423 other->contains(end_ - 1) || 422 other->contains(end_ - 1) ||
424 contains(other->start()) || 423 contains(other->start()) ||
425 contains(other->end() - 1); 424 contains(other->end() - 1);
426 } 425 }
427 426
428 intptr_t creation_serial() const { return creation_serial_; }
429 void set_creation_serial(intptr_t serial) {
430 creation_serial_ = serial;
431 }
432 int64_t compile_timestamp() const { return compile_timestamp_; } 427 int64_t compile_timestamp() const { return compile_timestamp_; }
433 void set_compile_timestamp(int64_t timestamp) { 428 void set_compile_timestamp(int64_t timestamp) {
434 compile_timestamp_ = timestamp; 429 compile_timestamp_ = timestamp;
435 } 430 }
436 431
437 intptr_t inclusive_ticks() const { return inclusive_ticks_; } 432 intptr_t inclusive_ticks() const { return inclusive_ticks_; }
438 void set_inclusive_ticks(intptr_t inclusive_ticks) { 433 void set_inclusive_ticks(intptr_t inclusive_ticks) {
439 inclusive_ticks_ = inclusive_ticks; 434 inclusive_ticks_ = inclusive_ticks;
440 } 435 }
441 void inc_inclusive_ticks() { 436 void inc_inclusive_ticks() {
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 case kReusedCode: 551 case kReusedCode:
557 return "Overwritten"; 552 return "Overwritten";
558 case kTagCode: 553 case kTagCode:
559 return "Tag"; 554 return "Tag";
560 } 555 }
561 UNREACHABLE(); 556 UNREACHABLE();
562 return NULL; 557 return NULL;
563 } 558 }
564 559
565 void DebugPrint() const { 560 void DebugPrint() const {
566 OS::Print("%s [%" Px ", %" Px ") %" Pd " %" Pd64 "\n", 561 OS::Print("%s [%" Px ", %" Px ") %" Pd64 "\n",
567 KindToCString(kind_), 562 KindToCString(kind_),
568 start(), 563 start(),
569 end(), 564 end(),
570 creation_serial_,
571 compile_timestamp_); 565 compile_timestamp_);
572 } 566 }
573 567
574 void Tick(uword pc, bool exclusive, intptr_t serial) { 568 void Tick(uword pc, bool exclusive, intptr_t serial) {
575 // Assert that exclusive ticks are never passed a valid serial number. 569 // Assert that exclusive ticks are never passed a valid serial number.
576 ASSERT((exclusive && (serial == -1)) || (!exclusive && (serial != -1))); 570 ASSERT((exclusive && (serial == -1)) || (!exclusive && (serial != -1)));
577 if (!exclusive && (inclusive_tick_serial_ == serial)) { 571 if (!exclusive && (inclusive_tick_serial_ == serial)) {
578 // We've already given this code object an inclusive tick for this sample. 572 // We've already given this code object an inclusive tick for this sample.
579 return; 573 return;
580 } 574 }
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
732 intptr_t inclusive_ticks_; 726 intptr_t inclusive_ticks_;
733 // Exclusive ticks. 727 // Exclusive ticks.
734 intptr_t exclusive_ticks_; 728 intptr_t exclusive_ticks_;
735 // Inclusive tick serial number, ensures that each CodeRegion is only given 729 // Inclusive tick serial number, ensures that each CodeRegion is only given
736 // a single inclusive tick per sample. 730 // a single inclusive tick per sample.
737 intptr_t inclusive_tick_serial_; 731 intptr_t inclusive_tick_serial_;
738 // Name of code region. 732 // Name of code region.
739 const char* name_; 733 const char* name_;
740 // The compilation timestamp associated with this code region. 734 // The compilation timestamp associated with this code region.
741 int64_t compile_timestamp_; 735 int64_t compile_timestamp_;
742 // Serial number at which this CodeRegion was created.
743 intptr_t creation_serial_;
744 // Dart code object (may be null). 736 // Dart code object (may be null).
745 const Code& code_; 737 const Code& code_;
746 // Pointer to ProfileFunction. 738 // Pointer to ProfileFunction.
747 ProfileFunction* profile_function_; 739 ProfileFunction* profile_function_;
748 // Final code table index. 740 // Final code table index.
749 intptr_t code_table_index_; 741 intptr_t code_table_index_;
750 ZoneGrowableArray<AddressEntry> address_table_; 742 ZoneGrowableArray<AddressEntry> address_table_;
751 DISALLOW_COPY_AND_ASSIGN(CodeRegion); 743 DISALLOW_COPY_AND_ASSIGN(CodeRegion);
752 }; 744 };
753 745
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 !b->contains(a->start()) && 935 !b->contains(a->start()) &&
944 !b->contains(a->end() - 1)); 936 !b->contains(a->end() - 1));
945 } 937 }
946 } 938 }
947 } 939 }
948 940
949 ZoneGrowableArray<CodeRegion*>* code_region_table_; 941 ZoneGrowableArray<CodeRegion*>* code_region_table_;
950 }; 942 };
951 943
952 944
953 class CodeRegionTableBuilder : public SampleVisitor { 945 class CodeRegionTableBuilder {
954 public: 946 public:
955 CodeRegionTableBuilder(Isolate* isolate, 947 CodeRegionTableBuilder(Isolate* isolate,
956 CodeRegionTable* live_code_table, 948 CodeRegionTable* live_code_table,
957 CodeRegionTable* dead_code_table, 949 CodeRegionTable* dead_code_table,
958 CodeRegionTable* tag_code_table, 950 CodeRegionTable* tag_code_table,
959 DeoptimizedCodeSet* deoptimized_code) 951 DeoptimizedCodeSet* deoptimized_code)
960 : SampleVisitor(isolate), 952 : live_code_table_(live_code_table),
961 live_code_table_(live_code_table),
962 dead_code_table_(dead_code_table), 953 dead_code_table_(dead_code_table),
963 tag_code_table_(tag_code_table), 954 tag_code_table_(tag_code_table),
964 isolate_(isolate), 955 isolate_(isolate),
965 vm_isolate_(Dart::vm_isolate()), 956 vm_isolate_(Dart::vm_isolate()),
966 null_code_(Code::ZoneHandle()), 957 null_code_(Code::ZoneHandle()),
967 deoptimized_code_(deoptimized_code) { 958 deoptimized_code_(deoptimized_code) {
968 ASSERT(live_code_table_ != NULL); 959 ASSERT(live_code_table_ != NULL);
969 ASSERT(dead_code_table_ != NULL); 960 ASSERT(dead_code_table_ != NULL);
970 ASSERT(tag_code_table_ != NULL); 961 ASSERT(tag_code_table_ != NULL);
971 ASSERT(isolate_ != NULL); 962 ASSERT(isolate_ != NULL);
972 ASSERT(vm_isolate_ != NULL); 963 ASSERT(vm_isolate_ != NULL);
973 ASSERT(null_code_.IsNull()); 964 ASSERT(null_code_.IsNull());
974 frames_ = 0; 965 frames_ = 0;
975 min_time_ = kMaxInt64; 966 min_time_ = kMaxInt64;
976 max_time_ = 0; 967 max_time_ = 0;
977 } 968 }
978 969
979 void VisitSample(Sample* sample) { 970 void VisitSample(intptr_t index, ProcessedSample* sample) {
980 int64_t timestamp = sample->timestamp(); 971 int64_t timestamp = sample->timestamp();
981 if (timestamp > max_time_) { 972 if (timestamp > max_time_) {
982 max_time_ = timestamp; 973 max_time_ = timestamp;
983 } 974 }
984 if (timestamp < min_time_) { 975 if (timestamp < min_time_) {
985 min_time_ = timestamp; 976 min_time_ = timestamp;
986 } 977 }
987 // Make sure VM tag is created. 978 // Make sure VM tag is created.
988 if (VMTag::IsNativeEntryTag(sample->vm_tag())) { 979 if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
989 CreateTag(VMTag::kNativeTagId); 980 CreateTag(VMTag::kNativeTagId);
990 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { 981 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
991 CreateTag(VMTag::kRuntimeTagId); 982 CreateTag(VMTag::kRuntimeTagId);
992 } 983 }
993 CreateTag(sample->vm_tag()); 984 CreateTag(sample->vm_tag());
994 // Make sure user tag is created. 985 // Make sure user tag is created.
995 CreateUserTag(sample->user_tag()); 986 CreateUserTag(sample->user_tag());
996 // Exclusive tick for top frame if we aren't sampled from an exit frame. 987 // Exclusive tick for top frame if we aren't sampled from an exit frame.
997 if (!sample->exit_frame_sample()) { 988 if (!sample->first_frame_executing()) {
998 Tick(sample->At(0), true, timestamp); 989 Tick(sample->At(0), true, index, timestamp);
999 } 990 }
1000 // Inclusive tick for all frames. 991 // Inclusive tick for all frames.
1001 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 992 for (intptr_t i = 0; i < sample->length(); i++) {
1002 if (sample->At(i) == 0) { 993 if (sample->At(i) == 0) {
1003 break; 994 break;
1004 } 995 }
1005 frames_++; 996 frames_++;
1006 Tick(sample->At(i), false, timestamp); 997 Tick(sample->At(i), false, index, timestamp);
1007 } 998 }
1008 } 999 }
1009 1000
1001 void Build(ProcessedSampleBuffer* buffer) {
1002 for (intptr_t i = 0; i < buffer->length(); i++) {
1003 ProcessedSample* sample = buffer->At(i);
1004 VisitSample(i, sample);
1005 }
1006 }
1007
1010 intptr_t frames() const { return frames_; } 1008 intptr_t frames() const { return frames_; }
1011 1009
1012 intptr_t TimeDeltaMicros() const { 1010 intptr_t TimeDeltaMicros() const {
1013 return static_cast<intptr_t>(max_time_ - min_time_); 1011 return static_cast<intptr_t>(max_time_ - min_time_);
1014 } 1012 }
1015 int64_t max_time() const { return max_time_; } 1013 int64_t max_time() const { return max_time_; }
1016 1014
1017 private: 1015 private:
1018 void CreateTag(uword tag) { 1016 void CreateTag(uword tag) {
1019 intptr_t index = tag_code_table_->FindIndex(tag); 1017 intptr_t index = tag_code_table_->FindIndex(tag);
1020 if (index >= 0) { 1018 if (index >= 0) {
1021 // Already created. 1019 // Already created.
1022 return; 1020 return;
1023 } 1021 }
1024 CodeRegion* region = new CodeRegion(CodeRegion::kTagCode, 1022 CodeRegion* region = new CodeRegion(CodeRegion::kTagCode,
1025 tag, 1023 tag,
1026 tag + 1, 1024 tag + 1,
1027 0, 1025 0,
1028 null_code_); 1026 null_code_);
1029 index = tag_code_table_->InsertCodeRegion(region); 1027 index = tag_code_table_->InsertCodeRegion(region);
1030 ASSERT(index >= 0); 1028 ASSERT(index >= 0);
1031 region->set_creation_serial(visited());
1032 } 1029 }
1033 1030
1034 void CreateUserTag(uword tag) { 1031 void CreateUserTag(uword tag) {
1035 if (tag == 0) { 1032 if (tag == 0) {
1036 // None set. 1033 // None set.
1037 return; 1034 return;
1038 } 1035 }
1039 return CreateTag(tag); 1036 return CreateTag(tag);
1040 } 1037 }
1041 1038
1042 void Tick(uword pc, bool exclusive, int64_t timestamp) { 1039 void Tick(uword pc, bool exclusive, intptr_t sample_idx, int64_t timestamp) {
1043 CodeRegionTable::TickResult r; 1040 CodeRegionTable::TickResult r;
1044 intptr_t serial = exclusive ? -1 : visited(); 1041 intptr_t serial = exclusive ? -1 : sample_idx;
1045 r = live_code_table_->Tick(pc, exclusive, serial, timestamp); 1042 r = live_code_table_->Tick(pc, exclusive, serial, timestamp);
1046 if (r == CodeRegionTable::kTicked) { 1043 if (r == CodeRegionTable::kTicked) {
1047 // Live code found and ticked. 1044 // Live code found and ticked.
1048 return; 1045 return;
1049 } 1046 }
1050 if (r == CodeRegionTable::kNewerCode) { 1047 if (r == CodeRegionTable::kNewerCode) {
1051 // Code has been overwritten by newer code. 1048 // Code has been overwritten by newer code.
1052 // Update shadow table of dead code regions. 1049 // Update shadow table of dead code regions.
1053 r = dead_code_table_->Tick(pc, exclusive, serial, timestamp); 1050 r = dead_code_table_->Tick(pc, exclusive, serial, timestamp);
1054 ASSERT(r != CodeRegionTable::kNewerCode); 1051 ASSERT(r != CodeRegionTable::kNewerCode);
1055 if (r == CodeRegionTable::kTicked) { 1052 if (r == CodeRegionTable::kTicked) {
1056 // Dead code found and ticked. 1053 // Dead code found and ticked.
1057 return; 1054 return;
1058 } 1055 }
1059 ASSERT(r == CodeRegionTable::kNotFound); 1056 ASSERT(r == CodeRegionTable::kNotFound);
1060 CreateAndTickDeadCodeRegion(pc, exclusive, serial); 1057 CreateAndTickDeadCodeRegion(pc, exclusive, serial);
1061 return; 1058 return;
1062 } 1059 }
1063 // Create new live CodeRegion. 1060 // Create new live CodeRegion.
1064 ASSERT(r == CodeRegionTable::kNotFound); 1061 ASSERT(r == CodeRegionTable::kNotFound);
1065 CodeRegion* region = CreateCodeRegion(pc); 1062 CodeRegion* region = CreateCodeRegion(pc);
1066 region->set_creation_serial(visited());
1067 intptr_t index = live_code_table_->InsertCodeRegion(region); 1063 intptr_t index = live_code_table_->InsertCodeRegion(region);
1068 ASSERT(index >= 0); 1064 ASSERT(index >= 0);
1069 region = live_code_table_->At(index); 1065 region = live_code_table_->At(index);
1070 if (region->compile_timestamp() <= timestamp) { 1066 if (region->compile_timestamp() <= timestamp) {
1071 region->Tick(pc, exclusive, serial); 1067 region->Tick(pc, exclusive, serial);
1072 return; 1068 return;
1073 } 1069 }
1074 // We have created a new code region but it's for a CodeRegion 1070 // We have created a new code region but it's for a CodeRegion
1075 // compiled after the sample. 1071 // compiled after the sample.
1076 ASSERT(region->kind() == CodeRegion::kDartCode); 1072 ASSERT(region->kind() == CodeRegion::kDartCode);
1077 CreateAndTickDeadCodeRegion(pc, exclusive, serial); 1073 CreateAndTickDeadCodeRegion(pc, exclusive, serial);
1078 } 1074 }
1079 1075
1080 void CreateAndTickDeadCodeRegion(uword pc, bool exclusive, intptr_t serial) { 1076 void CreateAndTickDeadCodeRegion(uword pc, bool exclusive, intptr_t serial) {
1081 // Need to create dead code. 1077 // Need to create dead code.
1082 CodeRegion* region = new CodeRegion(CodeRegion::kReusedCode, 1078 CodeRegion* region = new CodeRegion(CodeRegion::kReusedCode,
1083 pc, 1079 pc,
1084 pc + 1, 1080 pc + 1,
1085 0, 1081 0,
1086 null_code_); 1082 null_code_);
1087 intptr_t index = dead_code_table_->InsertCodeRegion(region); 1083 intptr_t index = dead_code_table_->InsertCodeRegion(region);
1088 region->set_creation_serial(visited());
1089 ASSERT(index >= 0); 1084 ASSERT(index >= 0);
1090 dead_code_table_->At(index)->Tick(pc, exclusive, serial); 1085 dead_code_table_->At(index)->Tick(pc, exclusive, serial);
1091 } 1086 }
1092 1087
1093 CodeRegion* CreateCodeRegion(uword pc) { 1088 CodeRegion* CreateCodeRegion(uword pc) {
1094 const intptr_t kDartCodeAlignment = OS::PreferredCodeAlignment(); 1089 const intptr_t kDartCodeAlignment = OS::PreferredCodeAlignment();
1095 const intptr_t kDartCodeAlignmentMask = ~(kDartCodeAlignment - 1); 1090 const intptr_t kDartCodeAlignmentMask = ~(kDartCodeAlignment - 1);
1096 Code& code = Code::Handle(isolate_); 1091 Code& code = Code::Handle(isolate_);
1097 // Check current isolate for pc. 1092 // Check current isolate for pc.
1098 if (isolate_->heap()->CodeContains(pc)) { 1093 if (isolate_->heap()->CodeContains(pc)) {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1191 tag_code_table_->FindIndex(VMTag::kTruncatedTagId); 1186 tag_code_table_->FindIndex(VMTag::kTruncatedTagId);
1192 ASSERT(truncated_index < 0); 1187 ASSERT(truncated_index < 0);
1193 CodeRegion* truncated = 1188 CodeRegion* truncated =
1194 new CodeRegion(CodeRegion::kTagCode, 1189 new CodeRegion(CodeRegion::kTagCode,
1195 VMTag::kTruncatedTagId, 1190 VMTag::kTruncatedTagId,
1196 VMTag::kTruncatedTagId + 1, 1191 VMTag::kTruncatedTagId + 1,
1197 0, 1192 0,
1198 null_code); 1193 null_code);
1199 truncated_index = tag_code_table_->InsertCodeRegion(truncated); 1194 truncated_index = tag_code_table_->InsertCodeRegion(truncated);
1200 ASSERT(truncated_index >= 0); 1195 ASSERT(truncated_index >= 0);
1201 truncated->set_creation_serial(0);
1202 1196
1203 // Create the root tag. 1197 // Create the root tag.
1204 intptr_t root_index = tag_code_table_->FindIndex(VMTag::kRootTagId); 1198 intptr_t root_index = tag_code_table_->FindIndex(VMTag::kRootTagId);
1205 ASSERT(root_index < 0); 1199 ASSERT(root_index < 0);
1206 CodeRegion* root = new CodeRegion(CodeRegion::kTagCode, 1200 CodeRegion* root = new CodeRegion(CodeRegion::kTagCode,
1207 VMTag::kRootTagId, 1201 VMTag::kRootTagId,
1208 VMTag::kRootTagId + 1, 1202 VMTag::kRootTagId + 1,
1209 0, 1203 0,
1210 null_code); 1204 null_code);
1211 root_index = tag_code_table_->InsertCodeRegion(root); 1205 root_index = tag_code_table_->InsertCodeRegion(root);
1212 ASSERT(root_index >= 0); 1206 ASSERT(root_index >= 0);
1213 root->set_creation_serial(0);
1214 } 1207 }
1215 1208
1216 void Map() { 1209 void Map() {
1217 // Calculate final indexes in code table for each CodeRegion. 1210 // Calculate final indexes in code table for each CodeRegion.
1218 for (intptr_t i = 0; i < live_code_table_->Length(); i++) { 1211 for (intptr_t i = 0; i < live_code_table_->Length(); i++) {
1219 const intptr_t index = i; 1212 const intptr_t index = i;
1220 CodeRegion* region = live_code_table_->At(i); 1213 CodeRegion* region = live_code_table_->At(i);
1221 ASSERT(region != NULL); 1214 ASSERT(region != NULL);
1222 region->set_code_table_index(index); 1215 region->set_code_table_index(index);
1223 } 1216 }
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 return (*b)->count() - (*a)->count(); 1395 return (*b)->count() - (*a)->count();
1403 } 1396 }
1404 1397
1405 const intptr_t profile_function_table_index_; 1398 const intptr_t profile_function_table_index_;
1406 intptr_t count_; 1399 intptr_t count_;
1407 ZoneGrowableArray<ProfileFunctionTrieNode*> children_; 1400 ZoneGrowableArray<ProfileFunctionTrieNode*> children_;
1408 ZoneGrowableArray<ProfileFunctionTrieNodeCode>* code_objects_; 1401 ZoneGrowableArray<ProfileFunctionTrieNodeCode>* code_objects_;
1409 }; 1402 };
1410 1403
1411 1404
1412 class ProfileFunctionTrieBuilder : public SampleVisitor { 1405 class ProfileFunctionTrieBuilder {
1413 public: 1406 public:
1414 ProfileFunctionTrieBuilder(Isolate* isolate, 1407 ProfileFunctionTrieBuilder(CodeRegionTable* live_code_table,
1415 CodeRegionTable* live_code_table,
1416 CodeRegionTable* dead_code_table, 1408 CodeRegionTable* dead_code_table,
1417 CodeRegionTable* tag_code_table, 1409 CodeRegionTable* tag_code_table,
1418 ProfileFunctionTable* function_table) 1410 ProfileFunctionTable* function_table)
1419 : SampleVisitor(isolate), 1411 : live_code_table_(live_code_table),
1420 live_code_table_(live_code_table),
1421 dead_code_table_(dead_code_table), 1412 dead_code_table_(dead_code_table),
1422 tag_code_table_(tag_code_table), 1413 tag_code_table_(tag_code_table),
1423 function_table_(function_table), 1414 function_table_(function_table),
1424 inclusive_tree_(false), 1415 inclusive_tree_(false) {
1425 trace_(false),
1426 trace_code_filter_(NULL) {
1427 ASSERT(live_code_table_ != NULL); 1416 ASSERT(live_code_table_ != NULL);
1428 ASSERT(dead_code_table_ != NULL); 1417 ASSERT(dead_code_table_ != NULL);
1429 ASSERT(tag_code_table_ != NULL); 1418 ASSERT(tag_code_table_ != NULL);
1430 ASSERT(function_table_ != NULL); 1419 ASSERT(function_table_ != NULL);
1431 set_tag_order(ProfilerService::kUserVM); 1420 set_tag_order(ProfilerService::kUserVM);
1432 1421
1433 // Verify that the truncated tag exists. 1422 // Verify that the truncated tag exists.
1434 ASSERT(tag_code_table_->FindIndex(VMTag::kTruncatedTagId) >= 0); 1423 ASSERT(tag_code_table_->FindIndex(VMTag::kTruncatedTagId) >= 0);
1435 1424
1436 // Verify that the root tag exists. 1425 // Verify that the root tag exists.
1437 intptr_t root_index = tag_code_table_->FindIndex(VMTag::kRootTagId); 1426 intptr_t root_index = tag_code_table_->FindIndex(VMTag::kRootTagId);
1438 ASSERT(root_index >= 0); 1427 ASSERT(root_index >= 0);
1439 1428
1440 // Setup root. 1429 // Setup root.
1441 CodeRegion* region = tag_code_table_->At(root_index); 1430 CodeRegion* region = tag_code_table_->At(root_index);
1442 ASSERT(region != NULL); 1431 ASSERT(region != NULL);
1443 ProfileFunction* function = region->function(); 1432 ProfileFunction* function = region->function();
1444 ASSERT(function != NULL); 1433 ASSERT(function != NULL);
1445 1434
1446 exclusive_root_ = new ProfileFunctionTrieNode(function->index()); 1435 exclusive_root_ = new ProfileFunctionTrieNode(function->index());
1447 inclusive_root_ = new ProfileFunctionTrieNode(function->index()); 1436 inclusive_root_ = new ProfileFunctionTrieNode(function->index());
1448 } 1437 }
1449 1438
1450 void VisitSample(Sample* sample) { 1439 void VisitSample(intptr_t sample_idx, ProcessedSample* sample) {
1451 inclusive_tree_ = false; 1440 inclusive_tree_ = false;
1452 ProcessSampleExclusive(sample); 1441 ProcessSampleExclusive(sample_idx, sample);
1453 inclusive_tree_ = true; 1442 inclusive_tree_ = true;
1454 ProcessSampleInclusive(sample); 1443 ProcessSampleInclusive(sample_idx, sample);
1444 }
1445
1446 void Build(ProcessedSampleBuffer* buffer) {
1447 for (intptr_t i = 0; i < buffer->length(); i++) {
1448 ProcessedSample* sample = buffer->At(i);
1449 VisitSample(i, sample);
1450 }
1455 } 1451 }
1456 1452
1457 ProfileFunctionTrieNode* exclusive_root() const { 1453 ProfileFunctionTrieNode* exclusive_root() const {
1458 return exclusive_root_; 1454 return exclusive_root_;
1459 } 1455 }
1460 1456
1461 ProfileFunctionTrieNode* inclusive_root() const { 1457 ProfileFunctionTrieNode* inclusive_root() const {
1462 return inclusive_root_; 1458 return inclusive_root_;
1463 } 1459 }
1464 1460
1465 ProfilerService::TagOrder tag_order() const { 1461 ProfilerService::TagOrder tag_order() const {
1466 return tag_order_; 1462 return tag_order_;
1467 } 1463 }
1468 1464
1469 bool vm_tags_emitted() const { 1465 bool vm_tags_emitted() const {
1470 return (tag_order_ == ProfilerService::kUserVM) || 1466 return (tag_order_ == ProfilerService::kUserVM) ||
1471 (tag_order_ == ProfilerService::kVMUser) || 1467 (tag_order_ == ProfilerService::kVMUser) ||
1472 (tag_order_ == ProfilerService::kVM); 1468 (tag_order_ == ProfilerService::kVM);
1473 } 1469 }
1474 1470
1475 void set_tag_order(ProfilerService::TagOrder tag_order) { 1471 void set_tag_order(ProfilerService::TagOrder tag_order) {
1476 tag_order_ = tag_order; 1472 tag_order_ = tag_order;
1477 } 1473 }
1478 1474
1479 private: 1475 private:
1480 void ProcessSampleInclusive(Sample* sample) { 1476 void ProcessSampleInclusive(intptr_t sample_idx, ProcessedSample* sample) {
1481 // Give the root a tick. 1477 // Give the root a tick.
1482 inclusive_root_->Tick(); 1478 inclusive_root_->Tick();
1483 ProfileFunctionTrieNode* current = inclusive_root_; 1479 ProfileFunctionTrieNode* current = inclusive_root_;
1484 current = AppendTags(sample, current); 1480 current = AppendTags(sample, current);
1485 if (sample->truncated_trace()) { 1481 if (sample->truncated()) {
1486 InclusiveTickTruncatedTag(); 1482 InclusiveTickTruncatedTag();
1487 current = AppendTruncatedTag(current); 1483 current = AppendTruncatedTag(current);
1488 } 1484 }
1489 // Walk the sampled PCs. 1485 // Walk the sampled PCs.
1490 for (intptr_t i = FLAG_profile_depth - 1; i >= 0; i--) { 1486 for (intptr_t i = sample->length() - 1; i >= 0; i--) {
1491 if (sample->At(i) == 0) { 1487 if (sample->At(i) == 0) {
1492 continue; 1488 continue;
1493 } 1489 }
1494 current = ProcessPC(sample->At(i), 1490 current = ProcessPC(sample->At(i),
1495 sample->timestamp(), 1491 sample->timestamp(),
1496 current, 1492 current,
1497 visited(), 1493 sample_idx,
1498 (i == 0), 1494 (i == 0),
1499 sample->exit_frame_sample() && (i == 0), 1495 !sample->first_frame_executing() && (i == 0));
1500 sample->missing_frame_inserted());
1501 } 1496 }
1502 } 1497 }
1503 1498
1504 void ProcessSampleExclusive(Sample* sample) { 1499 void ProcessSampleExclusive(intptr_t sample_idx, ProcessedSample* sample) {
1505 // Give the root a tick. 1500 // Give the root a tick.
1506 exclusive_root_->Tick(); 1501 exclusive_root_->Tick();
1507 ProfileFunctionTrieNode* current = exclusive_root_; 1502 ProfileFunctionTrieNode* current = exclusive_root_;
1508 current = AppendTags(sample, current); 1503 current = AppendTags(sample, current);
1509 // Walk the sampled PCs. 1504 // Walk the sampled PCs.
1510 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 1505 for (intptr_t i = 0; i < sample->length(); i++) {
1511 if (sample->At(i) == 0) { 1506 if (sample->At(i) == 0) {
1512 break; 1507 break;
1513 } 1508 }
1514 current = ProcessPC(sample->At(i), 1509 current = ProcessPC(sample->At(i),
1515 sample->timestamp(), 1510 sample->timestamp(),
1516 current, 1511 current,
1517 visited(), 1512 sample_idx,
1518 (i == 0), 1513 (i == 0),
1519 sample->exit_frame_sample() && (i == 0), 1514 !sample->first_frame_executing() && (i == 0));
1520 sample->missing_frame_inserted());
1521 } 1515 }
1522 if (sample->truncated_trace()) { 1516 if (sample->truncated()) {
1523 current = AppendTruncatedTag(current); 1517 current = AppendTruncatedTag(current);
1524 } 1518 }
1525 } 1519 }
1526 1520
1527 ProfileFunctionTrieNode* AppendUserTag(Sample* sample, 1521 ProfileFunctionTrieNode* AppendUserTag(ProcessedSample* sample,
1528 ProfileFunctionTrieNode* current) { 1522 ProfileFunctionTrieNode* current) {
1529 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); 1523 intptr_t user_tag_index = FindTagIndex(sample->user_tag());
1530 if (user_tag_index >= 0) { 1524 if (user_tag_index >= 0) {
1531 current = current->GetChild(user_tag_index); 1525 current = current->GetChild(user_tag_index);
1532 // Give the tag a tick. 1526 // Give the tag a tick.
1533 current->Tick(); 1527 current->Tick();
1534 } 1528 }
1535 return current; 1529 return current;
1536 } 1530 }
1537 1531
1538 1532
1539 ProfileFunctionTrieNode* AppendTruncatedTag( 1533 ProfileFunctionTrieNode* AppendTruncatedTag(
1540 ProfileFunctionTrieNode* current) { 1534 ProfileFunctionTrieNode* current) {
1541 intptr_t truncated_tag_index = FindTagIndex(VMTag::kTruncatedTagId); 1535 intptr_t truncated_tag_index = FindTagIndex(VMTag::kTruncatedTagId);
1542 ASSERT(truncated_tag_index >= 0); 1536 ASSERT(truncated_tag_index >= 0);
1543 current = current->GetChild(truncated_tag_index); 1537 current = current->GetChild(truncated_tag_index);
1544 current->Tick(); 1538 current->Tick();
1545 return current; 1539 return current;
1546 } 1540 }
1547 1541
1548 void InclusiveTickTruncatedTag() { 1542 void InclusiveTickTruncatedTag() {
1549 intptr_t index = tag_code_table_->FindIndex(VMTag::kTruncatedTagId); 1543 intptr_t index = tag_code_table_->FindIndex(VMTag::kTruncatedTagId);
1550 CodeRegion* region = tag_code_table_->At(index); 1544 CodeRegion* region = tag_code_table_->At(index);
1551 ProfileFunction* function = region->function(); 1545 ProfileFunction* function = region->function();
1552 function->inc_inclusive_ticks(); 1546 function->inc_inclusive_ticks();
1553 } 1547 }
1554 1548
1555 ProfileFunctionTrieNode* AppendVMTag(Sample* sample, 1549 ProfileFunctionTrieNode* AppendVMTag(ProcessedSample* sample,
1556 ProfileFunctionTrieNode* current) { 1550 ProfileFunctionTrieNode* current) {
1557 if (VMTag::IsNativeEntryTag(sample->vm_tag())) { 1551 if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
1558 // Insert a dummy kNativeTagId node. 1552 // Insert a dummy kNativeTagId node.
1559 intptr_t tag_index = FindTagIndex(VMTag::kNativeTagId); 1553 intptr_t tag_index = FindTagIndex(VMTag::kNativeTagId);
1560 current = current->GetChild(tag_index); 1554 current = current->GetChild(tag_index);
1561 // Give the tag a tick. 1555 // Give the tag a tick.
1562 current->Tick(); 1556 current->Tick();
1563 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { 1557 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
1564 // Insert a dummy kRuntimeTagId node. 1558 // Insert a dummy kRuntimeTagId node.
1565 intptr_t tag_index = FindTagIndex(VMTag::kRuntimeTagId); 1559 intptr_t tag_index = FindTagIndex(VMTag::kRuntimeTagId);
1566 current = current->GetChild(tag_index); 1560 current = current->GetChild(tag_index);
1567 // Give the tag a tick. 1561 // Give the tag a tick.
1568 current->Tick(); 1562 current->Tick();
1569 } else { 1563 } else {
1570 intptr_t tag_index = FindTagIndex(sample->vm_tag()); 1564 intptr_t tag_index = FindTagIndex(sample->vm_tag());
1571 current = current->GetChild(tag_index); 1565 current = current->GetChild(tag_index);
1572 // Give the tag a tick. 1566 // Give the tag a tick.
1573 current->Tick(); 1567 current->Tick();
1574 } 1568 }
1575 return current; 1569 return current;
1576 } 1570 }
1577 1571
1578 ProfileFunctionTrieNode* AppendSpecificNativeRuntimeEntryVMTag( 1572 ProfileFunctionTrieNode* AppendSpecificNativeRuntimeEntryVMTag(
1579 Sample* sample, ProfileFunctionTrieNode* current) { 1573 ProcessedSample* sample, ProfileFunctionTrieNode* current) {
1580 // Only Native and Runtime entries have a second VM tag. 1574 // Only Native and Runtime entries have a second VM tag.
1581 if (!VMTag::IsNativeEntryTag(sample->vm_tag()) && 1575 if (!VMTag::IsNativeEntryTag(sample->vm_tag()) &&
1582 !VMTag::IsRuntimeEntryTag(sample->vm_tag())) { 1576 !VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
1583 return current; 1577 return current;
1584 } 1578 }
1585 intptr_t tag_index = FindTagIndex(sample->vm_tag()); 1579 intptr_t tag_index = FindTagIndex(sample->vm_tag());
1586 current = current->GetChild(tag_index); 1580 current = current->GetChild(tag_index);
1587 // Give the tag a tick. 1581 // Give the tag a tick.
1588 current->Tick(); 1582 current->Tick();
1589 return current; 1583 return current;
1590 } 1584 }
1591 1585
1592 ProfileFunctionTrieNode* AppendVMTags(Sample* sample, 1586 ProfileFunctionTrieNode* AppendVMTags(ProcessedSample* sample,
1593 ProfileFunctionTrieNode* current) { 1587 ProfileFunctionTrieNode* current) {
1594 current = AppendVMTag(sample, current); 1588 current = AppendVMTag(sample, current);
1595 current = AppendSpecificNativeRuntimeEntryVMTag(sample, current); 1589 current = AppendSpecificNativeRuntimeEntryVMTag(sample, current);
1596 return current; 1590 return current;
1597 } 1591 }
1598 1592
1599 ProfileFunctionTrieNode* AppendTags(Sample* sample, 1593 ProfileFunctionTrieNode* AppendTags(ProcessedSample* sample,
1600 ProfileFunctionTrieNode* current) { 1594 ProfileFunctionTrieNode* current) {
1601 // None. 1595 // None.
1602 if (tag_order() == ProfilerService::kNoTags) { 1596 if (tag_order() == ProfilerService::kNoTags) {
1603 return current; 1597 return current;
1604 } 1598 }
1605 // User first. 1599 // User first.
1606 if ((tag_order() == ProfilerService::kUserVM) || 1600 if ((tag_order() == ProfilerService::kUserVM) ||
1607 (tag_order() == ProfilerService::kUser)) { 1601 (tag_order() == ProfilerService::kUser)) {
1608 current = AppendUserTag(sample, current); 1602 current = AppendUserTag(sample, current);
1609 // Only user. 1603 // Only user.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1646 ProfileFunction* function = function_table_->At(current_index); 1640 ProfileFunction* function = function_table_->At(current_index);
1647 function->Dump(); 1641 function->Dump();
1648 OS::Print("\n"); 1642 OS::Print("\n");
1649 } 1643 }
1650 1644
1651 ProfileFunctionTrieNode* ProcessPC(uword pc, 1645 ProfileFunctionTrieNode* ProcessPC(uword pc,
1652 int64_t timestamp, 1646 int64_t timestamp,
1653 ProfileFunctionTrieNode* current, 1647 ProfileFunctionTrieNode* current,
1654 intptr_t inclusive_serial, 1648 intptr_t inclusive_serial,
1655 bool top_frame, 1649 bool top_frame,
1656 bool exit_frame, 1650 bool exit_frame) {
1657 bool missing_frame_inserted) {
1658 CodeRegion* region = FindCodeObject(pc, timestamp); 1651 CodeRegion* region = FindCodeObject(pc, timestamp);
1659 if (region == NULL) { 1652 if (region == NULL) {
1660 return current; 1653 return current;
1661 } 1654 }
1662 const char* region_name = region->name(); 1655 const char* region_name = region->name();
1663 if (region_name == NULL) { 1656 if (region_name == NULL) {
1664 region_name = ""; 1657 region_name = "";
1665 } 1658 }
1666 intptr_t code_index = region->code_table_index(); 1659 intptr_t code_index = region->code_table_index();
1667 const Code& code = Code::ZoneHandle(region->code()); 1660 const Code& code = Code::ZoneHandle(region->code());
1668 GrowableArray<Function*> inlined_functions; 1661 GrowableArray<Function*> inlined_functions;
1669 if (!code.IsNull()) { 1662 if (!code.IsNull()) {
1670 intptr_t offset = pc - code.EntryPoint(); 1663 intptr_t offset = pc - code.EntryPoint();
1671 code.GetInlinedFunctionsAt(offset, &inlined_functions); 1664 code.GetInlinedFunctionsAt(offset, &inlined_functions);
1672 } 1665 }
1673 if (code.IsNull() || (inlined_functions.length() == 0)) { 1666 if (code.IsNull() || (inlined_functions.length() == 0)) {
1674 // No inlined functions. 1667 // No inlined functions.
1675 ProfileFunction* function = region->function(); 1668 ProfileFunction* function = region->function();
1676 ASSERT(function != NULL); 1669 ASSERT(function != NULL);
1677 if (trace_) {
1678 OS::Print("[%" Px "] X - %s (%s)\n",
1679 pc, function->name(), region_name);
1680 }
1681 current = ProcessFunction(function, 1670 current = ProcessFunction(function,
1682 current, 1671 current,
1683 inclusive_serial, 1672 inclusive_serial,
1684 top_frame, 1673 top_frame,
1685 exit_frame, 1674 exit_frame,
1686 code_index); 1675 code_index);
1687 if ((trace_code_filter_ != NULL) &&
1688 (strstr(region_name, trace_code_filter_) != NULL)) {
1689 trace_ = true;
1690 OS::Print("Tracing from: %" Px " [%s] ", pc,
1691 missing_frame_inserted ? "INSERTED" : "");
1692 Dump(current);
1693 }
1694 return current; 1676 return current;
1695 } 1677 }
1696 1678
1697 if (inclusive_tree_) { 1679 if (inclusive_tree_) {
1698 for (intptr_t i = inlined_functions.length() - 1; i >= 0; i--) { 1680 for (intptr_t i = inlined_functions.length() - 1; i >= 0; i--) {
1699 Function* inlined_function = inlined_functions[i]; 1681 Function* inlined_function = inlined_functions[i];
1700 ASSERT(inlined_function != NULL); 1682 ASSERT(inlined_function != NULL);
1701 ASSERT(!inlined_function->IsNull()); 1683 ASSERT(!inlined_function->IsNull());
1702 current = ProcessInlinedFunction(inlined_function, 1684 current = ProcessInlinedFunction(inlined_function,
1703 current, 1685 current,
1704 inclusive_serial, 1686 inclusive_serial,
1705 top_frame, 1687 top_frame,
1706 exit_frame, 1688 exit_frame,
1707 code_index); 1689 code_index);
1708 top_frame = false; 1690 top_frame = false;
1709 } 1691 }
1710 } else { 1692 } else {
1711 for (intptr_t i = 0; i < inlined_functions.length(); i++) { 1693 for (intptr_t i = 0; i < inlined_functions.length(); i++) {
1712 Function* inlined_function = inlined_functions[i]; 1694 Function* inlined_function = inlined_functions[i];
1713 ASSERT(inlined_function != NULL); 1695 ASSERT(inlined_function != NULL);
1714 ASSERT(!inlined_function->IsNull()); 1696 ASSERT(!inlined_function->IsNull());
1715 const char* inline_name = inlined_function->ToQualifiedCString();
1716 if (trace_) {
1717 OS::Print("[%" Px "] %" Pd " - %s (%s)\n",
1718 pc, i, inline_name, region_name);
1719 }
1720 current = ProcessInlinedFunction(inlined_function, 1697 current = ProcessInlinedFunction(inlined_function,
1721 current, 1698 current,
1722 inclusive_serial, 1699 inclusive_serial,
1723 top_frame, 1700 top_frame,
1724 exit_frame, 1701 exit_frame,
1725 code_index); 1702 code_index);
1726 top_frame = false; 1703 top_frame = false;
1727 if ((trace_code_filter_ != NULL) &&
1728 (strstr(region_name, trace_code_filter_) != NULL)) {
1729 trace_ = true;
1730 OS::Print("Tracing from: %" Px " [%s] ",
1731 pc, missing_frame_inserted ? "INSERTED" : "");
1732 Dump(current);
1733 }
1734 } 1704 }
1735 } 1705 }
1736 1706
1737 return current; 1707 return current;
1738 } 1708 }
1739 1709
1740 ProfileFunctionTrieNode* ProcessInlinedFunction( 1710 ProfileFunctionTrieNode* ProcessInlinedFunction(
1741 Function* inlined_function, 1711 Function* inlined_function,
1742 ProfileFunctionTrieNode* current, 1712 ProfileFunctionTrieNode* current,
1743 intptr_t inclusive_serial, 1713 intptr_t inclusive_serial,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1804 } 1774 }
1805 1775
1806 ProfilerService::TagOrder tag_order_; 1776 ProfilerService::TagOrder tag_order_;
1807 ProfileFunctionTrieNode* exclusive_root_; 1777 ProfileFunctionTrieNode* exclusive_root_;
1808 ProfileFunctionTrieNode* inclusive_root_; 1778 ProfileFunctionTrieNode* inclusive_root_;
1809 CodeRegionTable* live_code_table_; 1779 CodeRegionTable* live_code_table_;
1810 CodeRegionTable* dead_code_table_; 1780 CodeRegionTable* dead_code_table_;
1811 CodeRegionTable* tag_code_table_; 1781 CodeRegionTable* tag_code_table_;
1812 ProfileFunctionTable* function_table_; 1782 ProfileFunctionTable* function_table_;
1813 bool inclusive_tree_; 1783 bool inclusive_tree_;
1814 bool trace_;
1815 const char* trace_code_filter_;
1816 }; 1784 };
1817 1785
1818 1786
1819 class CodeRegionTrieNode : public ZoneAllocated { 1787 class CodeRegionTrieNode : public ZoneAllocated {
1820 public: 1788 public:
1821 explicit CodeRegionTrieNode(intptr_t code_region_index) 1789 explicit CodeRegionTrieNode(intptr_t code_region_index)
1822 : code_region_index_(code_region_index), 1790 : code_region_index_(code_region_index),
1823 count_(0), 1791 count_(0),
1824 children_(new ZoneGrowableArray<CodeRegionTrieNode*>()) { 1792 children_(new ZoneGrowableArray<CodeRegionTrieNode*>()) {
1825 } 1793 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1901 ASSERT(b != NULL); 1869 ASSERT(b != NULL);
1902 return (*b)->count() - (*a)->count(); 1870 return (*b)->count() - (*a)->count();
1903 } 1871 }
1904 1872
1905 const intptr_t code_region_index_; 1873 const intptr_t code_region_index_;
1906 intptr_t count_; 1874 intptr_t count_;
1907 ZoneGrowableArray<CodeRegionTrieNode*>* children_; 1875 ZoneGrowableArray<CodeRegionTrieNode*>* children_;
1908 }; 1876 };
1909 1877
1910 1878
1911 class CodeRegionTrieBuilder : public SampleVisitor { 1879 class CodeRegionTrieBuilder {
1912 public: 1880 public:
1913 CodeRegionTrieBuilder(Isolate* isolate, 1881 CodeRegionTrieBuilder(Isolate* isolate,
1914 CodeRegionTable* live_code_table, 1882 CodeRegionTable* live_code_table,
1915 CodeRegionTable* dead_code_table, 1883 CodeRegionTable* dead_code_table,
1916 CodeRegionTable* tag_code_table) 1884 CodeRegionTable* tag_code_table)
1917 : SampleVisitor(isolate), 1885 : live_code_table_(live_code_table),
1918 live_code_table_(live_code_table),
1919 dead_code_table_(dead_code_table), 1886 dead_code_table_(dead_code_table),
1920 tag_code_table_(tag_code_table) { 1887 tag_code_table_(tag_code_table) {
1921 ASSERT(live_code_table_ != NULL); 1888 ASSERT(live_code_table_ != NULL);
1922 ASSERT(dead_code_table_ != NULL); 1889 ASSERT(dead_code_table_ != NULL);
1923 ASSERT(tag_code_table_ != NULL); 1890 ASSERT(tag_code_table_ != NULL);
1924 set_tag_order(ProfilerService::kUserVM); 1891 set_tag_order(ProfilerService::kUserVM);
1925 1892
1926 // Verify that the truncated tag exists. 1893 // Verify that the truncated tag exists.
1927 ASSERT(tag_code_table_->FindIndex(VMTag::kTruncatedTagId) >= 0); 1894 ASSERT(tag_code_table_->FindIndex(VMTag::kTruncatedTagId) >= 0);
1928 1895
1929 // Verify that the root tag exists. 1896 // Verify that the root tag exists.
1930 intptr_t root_index = tag_code_table_->FindIndex(VMTag::kRootTagId); 1897 intptr_t root_index = tag_code_table_->FindIndex(VMTag::kRootTagId);
1931 ASSERT(root_index >= 0); 1898 ASSERT(root_index >= 0);
1932 CodeRegion* region = tag_code_table_->At(root_index); 1899 CodeRegion* region = tag_code_table_->At(root_index);
1933 ASSERT(region != NULL); 1900 ASSERT(region != NULL);
1934 1901
1935 exclusive_root_ = new CodeRegionTrieNode(region->code_table_index()); 1902 exclusive_root_ = new CodeRegionTrieNode(region->code_table_index());
1936 inclusive_root_ = new CodeRegionTrieNode(region->code_table_index()); 1903 inclusive_root_ = new CodeRegionTrieNode(region->code_table_index());
1937 } 1904 }
1938 1905
1939 void VisitSample(Sample* sample) { 1906 void VisitSample(ProcessedSample* sample) {
1940 ProcessSampleExclusive(sample); 1907 ProcessSampleExclusive(sample);
1941 ProcessSampleInclusive(sample); 1908 ProcessSampleInclusive(sample);
1942 } 1909 }
1943 1910
1911 void Build(ProcessedSampleBuffer* buffer) {
1912 for (intptr_t i = 0; i < buffer->length(); i++) {
1913 ProcessedSample* sample = buffer->At(i);
1914 VisitSample(sample);
1915 }
1916 }
1917
1944 CodeRegionTrieNode* inclusive_root() const { 1918 CodeRegionTrieNode* inclusive_root() const {
1945 return inclusive_root_; 1919 return inclusive_root_;
1946 } 1920 }
1947 1921
1948 CodeRegionTrieNode* exclusive_root() const { 1922 CodeRegionTrieNode* exclusive_root() const {
1949 return exclusive_root_; 1923 return exclusive_root_;
1950 } 1924 }
1951 1925
1952 ProfilerService::TagOrder tag_order() const { 1926 ProfilerService::TagOrder tag_order() const {
1953 return tag_order_; 1927 return tag_order_;
1954 } 1928 }
1955 1929
1956 bool vm_tags_emitted() const { 1930 bool vm_tags_emitted() const {
1957 return (tag_order_ == ProfilerService::kUserVM) || 1931 return (tag_order_ == ProfilerService::kUserVM) ||
1958 (tag_order_ == ProfilerService::kVMUser) || 1932 (tag_order_ == ProfilerService::kVMUser) ||
1959 (tag_order_ == ProfilerService::kVM); 1933 (tag_order_ == ProfilerService::kVM);
1960 } 1934 }
1961 1935
1962 void set_tag_order(ProfilerService::TagOrder tag_order) { 1936 void set_tag_order(ProfilerService::TagOrder tag_order) {
1963 tag_order_ = tag_order; 1937 tag_order_ = tag_order;
1964 } 1938 }
1965 1939
1966 private: 1940 private:
1967 void ProcessSampleInclusive(Sample* sample) { 1941 void ProcessSampleInclusive(ProcessedSample* sample) {
1968 // Give the root a tick. 1942 // Give the root a tick.
1969 inclusive_root_->Tick(); 1943 inclusive_root_->Tick();
1970 CodeRegionTrieNode* current = inclusive_root_; 1944 CodeRegionTrieNode* current = inclusive_root_;
1971 current = AppendTags(sample, current); 1945 current = AppendTags(sample, current);
1972 if (sample->truncated_trace()) { 1946 if (sample->truncated()) {
1973 current = AppendTruncatedTag(current); 1947 current = AppendTruncatedTag(current);
1974 } 1948 }
1975 // Walk the sampled PCs. 1949 // Walk the sampled PCs.
1976 for (intptr_t i = FLAG_profile_depth - 1; i >= 0; i--) { 1950 for (intptr_t i = sample->length() - 1; i >= 0; i--) {
1977 if (sample->At(i) == 0) { 1951 if (sample->At(i) == 0) {
1978 continue; 1952 continue;
1979 } 1953 }
1980 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp()); 1954 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp());
1981 if (index < 0) { 1955 if (index < 0) {
1982 continue; 1956 continue;
1983 } 1957 }
1984 current = current->GetChild(index); 1958 current = current->GetChild(index);
1985 current->Tick(); 1959 current->Tick();
1986 } 1960 }
1987 } 1961 }
1988 1962
1989 void ProcessSampleExclusive(Sample* sample) { 1963 void ProcessSampleExclusive(ProcessedSample* sample) {
1990 // Give the root a tick. 1964 // Give the root a tick.
1991 exclusive_root_->Tick(); 1965 exclusive_root_->Tick();
1992 CodeRegionTrieNode* current = exclusive_root_; 1966 CodeRegionTrieNode* current = exclusive_root_;
1993 current = AppendTags(sample, current); 1967 current = AppendTags(sample, current);
1994 // Walk the sampled PCs. 1968 // Walk the sampled PCs.
1995 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 1969 for (intptr_t i = 0; i < sample->length(); i++) {
1996 if (sample->At(i) == 0) { 1970 if (sample->At(i) == 0) {
1997 break; 1971 break;
1998 } 1972 }
1999 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp()); 1973 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp());
2000 if (index < 0) { 1974 if (index < 0) {
2001 continue; 1975 continue;
2002 } 1976 }
2003 current = current->GetChild(index); 1977 current = current->GetChild(index);
2004 if (i == 0) { 1978 if (i == 0) {
2005 // Executing PC. 1979 // Executing PC.
2006 if (!sample->exit_frame_sample() || vm_tags_emitted()) { 1980 if (!sample->first_frame_executing() || vm_tags_emitted()) {
2007 // Only tick if this isn't an exit frame or VM tags are emitted. 1981 // Only tick if this isn't an exit frame or VM tags are emitted.
2008 current->Tick(); 1982 current->Tick();
2009 } 1983 }
2010 } else { 1984 } else {
2011 // Caller PCs. 1985 // Caller PCs.
2012 current->Tick(); 1986 current->Tick();
2013 } 1987 }
2014 } 1988 }
2015 if (sample->truncated_trace()) { 1989 if (sample->truncated()) {
2016 current = AppendTruncatedTag(current); 1990 current = AppendTruncatedTag(current);
2017 } 1991 }
2018 } 1992 }
2019 1993
2020 CodeRegionTrieNode* AppendUserTag(Sample* sample, 1994 CodeRegionTrieNode* AppendUserTag(ProcessedSample* sample,
2021 CodeRegionTrieNode* current) { 1995 CodeRegionTrieNode* current) {
2022 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); 1996 intptr_t user_tag_index = FindTagIndex(sample->user_tag());
2023 if (user_tag_index >= 0) { 1997 if (user_tag_index >= 0) {
2024 current = current->GetChild(user_tag_index); 1998 current = current->GetChild(user_tag_index);
2025 // Give the tag a tick. 1999 // Give the tag a tick.
2026 current->Tick(); 2000 current->Tick();
2027 } 2001 }
2028 return current; 2002 return current;
2029 } 2003 }
2030 2004
2031 CodeRegionTrieNode* AppendTruncatedTag(CodeRegionTrieNode* current) { 2005 CodeRegionTrieNode* AppendTruncatedTag(CodeRegionTrieNode* current) {
2032 intptr_t truncated_tag_index = FindTagIndex(VMTag::kTruncatedTagId); 2006 intptr_t truncated_tag_index = FindTagIndex(VMTag::kTruncatedTagId);
2033 ASSERT(truncated_tag_index >= 0); 2007 ASSERT(truncated_tag_index >= 0);
2034 current = current->GetChild(truncated_tag_index); 2008 current = current->GetChild(truncated_tag_index);
2035 current->Tick(); 2009 current->Tick();
2036 return current; 2010 return current;
2037 } 2011 }
2038 2012
2039 CodeRegionTrieNode* AppendVMTag(Sample* sample, 2013 CodeRegionTrieNode* AppendVMTag(ProcessedSample* sample,
2040 CodeRegionTrieNode* current) { 2014 CodeRegionTrieNode* current) {
2041 if (VMTag::IsNativeEntryTag(sample->vm_tag())) { 2015 if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
2042 // Insert a dummy kNativeTagId node. 2016 // Insert a dummy kNativeTagId node.
2043 intptr_t tag_index = FindTagIndex(VMTag::kNativeTagId); 2017 intptr_t tag_index = FindTagIndex(VMTag::kNativeTagId);
2044 current = current->GetChild(tag_index); 2018 current = current->GetChild(tag_index);
2045 // Give the tag a tick. 2019 // Give the tag a tick.
2046 current->Tick(); 2020 current->Tick();
2047 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { 2021 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
2048 // Insert a dummy kRuntimeTagId node. 2022 // Insert a dummy kRuntimeTagId node.
2049 intptr_t tag_index = FindTagIndex(VMTag::kRuntimeTagId); 2023 intptr_t tag_index = FindTagIndex(VMTag::kRuntimeTagId);
2050 current = current->GetChild(tag_index); 2024 current = current->GetChild(tag_index);
2051 // Give the tag a tick. 2025 // Give the tag a tick.
2052 current->Tick(); 2026 current->Tick();
2053 } else { 2027 } else {
2054 intptr_t tag_index = FindTagIndex(sample->vm_tag()); 2028 intptr_t tag_index = FindTagIndex(sample->vm_tag());
2055 current = current->GetChild(tag_index); 2029 current = current->GetChild(tag_index);
2056 // Give the tag a tick. 2030 // Give the tag a tick.
2057 current->Tick(); 2031 current->Tick();
2058 } 2032 }
2059 return current; 2033 return current;
2060 } 2034 }
2061 2035
2062 CodeRegionTrieNode* AppendSpecificNativeRuntimeEntryVMTag( 2036 CodeRegionTrieNode* AppendSpecificNativeRuntimeEntryVMTag(
2063 Sample* sample, CodeRegionTrieNode* current) { 2037 ProcessedSample* sample, CodeRegionTrieNode* current) {
2064 // Only Native and Runtime entries have a second VM tag. 2038 // Only Native and Runtime entries have a second VM tag.
2065 if (!VMTag::IsNativeEntryTag(sample->vm_tag()) && 2039 if (!VMTag::IsNativeEntryTag(sample->vm_tag()) &&
2066 !VMTag::IsRuntimeEntryTag(sample->vm_tag())) { 2040 !VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
2067 return current; 2041 return current;
2068 } 2042 }
2069 intptr_t tag_index = FindTagIndex(sample->vm_tag()); 2043 intptr_t tag_index = FindTagIndex(sample->vm_tag());
2070 current = current->GetChild(tag_index); 2044 current = current->GetChild(tag_index);
2071 // Give the tag a tick. 2045 // Give the tag a tick.
2072 current->Tick(); 2046 current->Tick();
2073 return current; 2047 return current;
2074 } 2048 }
2075 2049
2076 CodeRegionTrieNode* AppendVMTags(Sample* sample, 2050 CodeRegionTrieNode* AppendVMTags(ProcessedSample* sample,
2077 CodeRegionTrieNode* current) { 2051 CodeRegionTrieNode* current) {
2078 current = AppendVMTag(sample, current); 2052 current = AppendVMTag(sample, current);
2079 current = AppendSpecificNativeRuntimeEntryVMTag(sample, current); 2053 current = AppendSpecificNativeRuntimeEntryVMTag(sample, current);
2080 return current; 2054 return current;
2081 } 2055 }
2082 2056
2083 CodeRegionTrieNode* AppendTags(Sample* sample, CodeRegionTrieNode* current) { 2057 CodeRegionTrieNode* AppendTags(ProcessedSample* sample,
2058 CodeRegionTrieNode* current) {
2084 // None. 2059 // None.
2085 if (tag_order() == ProfilerService::kNoTags) { 2060 if (tag_order() == ProfilerService::kNoTags) {
2086 return current; 2061 return current;
2087 } 2062 }
2088 // User first. 2063 // User first.
2089 if ((tag_order() == ProfilerService::kUserVM) || 2064 if ((tag_order() == ProfilerService::kUserVM) ||
2090 (tag_order() == ProfilerService::kUser)) { 2065 (tag_order() == ProfilerService::kUser)) {
2091 current = AppendUserTag(sample, current); 2066 current = AppendUserTag(sample, current);
2092 // Only user. 2067 // Only user.
2093 if (tag_order() == ProfilerService::kUser) { 2068 if (tag_order() == ProfilerService::kUser) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
2168 if (profiler_data == NULL) { 2143 if (profiler_data == NULL) {
2169 stream->PrintError(kFeatureDisabled, NULL); 2144 stream->PrintError(kFeatureDisabled, NULL);
2170 return; 2145 return;
2171 } 2146 }
2172 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); 2147 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
2173 ASSERT(sample_buffer != NULL); 2148 ASSERT(sample_buffer != NULL);
2174 ScopeTimer sw("ProfilerService::PrintJSON", FLAG_trace_profiler); 2149 ScopeTimer sw("ProfilerService::PrintJSON", FLAG_trace_profiler);
2175 { 2150 {
2176 StackZone zone(isolate); 2151 StackZone zone(isolate);
2177 HANDLESCOPE(isolate); 2152 HANDLESCOPE(isolate);
2153
2154 ProcessedSampleBuffer* processed_samples = NULL;
2155 {
2156 ScopeTimer sw("BuildProcessedSampleBuffer", FLAG_trace_profiler);
2157 SampleFilter filter(isolate);
2158 processed_samples = sample_buffer->BuildProcessedSampleBuffer(&filter);
2159 }
2160
2178 { 2161 {
2179 // Live code holds Dart, Native, and Collected CodeRegions. 2162 // Live code holds Dart, Native, and Collected CodeRegions.
2180 CodeRegionTable live_code_table; 2163 CodeRegionTable live_code_table;
2181 // Dead code holds Overwritten CodeRegions. 2164 // Dead code holds Overwritten CodeRegions.
2182 CodeRegionTable dead_code_table; 2165 CodeRegionTable dead_code_table;
2183 // Tag code holds Tag CodeRegions. 2166 // Tag code holds Tag CodeRegions.
2184 CodeRegionTable tag_code_table; 2167 CodeRegionTable tag_code_table;
2185 // Table holding all ProfileFunctions. 2168 // Table holding all ProfileFunctions.
2186 ProfileFunctionTable function_table; 2169 ProfileFunctionTable function_table;
2187 // Set of deoptimized code still referenced by the profiler. 2170 // Set of deoptimized code still referenced by the profiler.
2188 DeoptimizedCodeSet* deoptimized_code = new DeoptimizedCodeSet(isolate); 2171 DeoptimizedCodeSet* deoptimized_code = new DeoptimizedCodeSet(isolate);
2189 2172
2190 {
2191 ScopeTimer sw("PreprocessSamples", FLAG_trace_profiler);
2192 // Preprocess samples.
2193 PreprocessVisitor preprocessor(isolate);
2194 sample_buffer->VisitSamples(&preprocessor);
2195 }
2196
2197 // Build CodeRegion tables. 2173 // Build CodeRegion tables.
2198 CodeRegionTableBuilder builder(isolate, 2174 CodeRegionTableBuilder builder(isolate,
2199 &live_code_table, 2175 &live_code_table,
2200 &dead_code_table, 2176 &dead_code_table,
2201 &tag_code_table, 2177 &tag_code_table,
2202 deoptimized_code); 2178 deoptimized_code);
2203 { 2179 {
2204 ScopeTimer sw("CodeRegionTableBuilder", FLAG_trace_profiler); 2180 ScopeTimer sw("CodeRegionTableBuilder::Build", FLAG_trace_profiler);
2205 sample_buffer->VisitSamples(&builder); 2181 builder.Build(processed_samples);
2206 } 2182 }
2207 intptr_t samples = builder.visited(); 2183 intptr_t samples = processed_samples->length();
2208 intptr_t frames = builder.frames(); 2184 intptr_t frames = builder.frames();
2209 if (FLAG_trace_profiler) { 2185 if (FLAG_trace_profiler) {
2210 intptr_t total_live_code_objects = live_code_table.Length(); 2186 intptr_t total_live_code_objects = live_code_table.Length();
2211 intptr_t total_dead_code_objects = dead_code_table.Length(); 2187 intptr_t total_dead_code_objects = dead_code_table.Length();
2212 intptr_t total_tag_code_objects = tag_code_table.Length(); 2188 intptr_t total_tag_code_objects = tag_code_table.Length();
2213 OS::Print( 2189 OS::Print(
2214 "Processed %" Pd " samples with %" Pd " frames\n", samples, frames); 2190 "Processed %" Pd " samples with %" Pd " frames\n", samples, frames);
2215 OS::Print("CodeTables: live=%" Pd " dead=%" Pd " tag=%" Pd "\n", 2191 OS::Print("CodeTables: live=%" Pd " dead=%" Pd " tag=%" Pd "\n",
2216 total_live_code_objects, 2192 total_live_code_objects,
2217 total_dead_code_objects, 2193 total_dead_code_objects,
(...skipping 19 matching lines...) Expand all
2237 intptr_t total_functions = function_table.Length(); 2213 intptr_t total_functions = function_table.Length();
2238 OS::Print("FunctionTable: size=%" Pd "\n", total_functions); 2214 OS::Print("FunctionTable: size=%" Pd "\n", total_functions);
2239 } 2215 }
2240 CodeRegionTrieBuilder code_trie_builder(isolate, 2216 CodeRegionTrieBuilder code_trie_builder(isolate,
2241 &live_code_table, 2217 &live_code_table,
2242 &dead_code_table, 2218 &dead_code_table,
2243 &tag_code_table); 2219 &tag_code_table);
2244 code_trie_builder.set_tag_order(tag_order); 2220 code_trie_builder.set_tag_order(tag_order);
2245 { 2221 {
2246 // Build CodeRegion trie. 2222 // Build CodeRegion trie.
2247 ScopeTimer sw("CodeRegionTrieBuilder", FLAG_trace_profiler); 2223 ScopeTimer sw("CodeRegionTrieBuilder::Build", FLAG_trace_profiler);
2248 sample_buffer->VisitSamples(&code_trie_builder); 2224 code_trie_builder.Build(processed_samples);
2249 code_trie_builder.exclusive_root()->SortByCount(); 2225 code_trie_builder.exclusive_root()->SortByCount();
2250 code_trie_builder.inclusive_root()->SortByCount(); 2226 code_trie_builder.inclusive_root()->SortByCount();
2251 } 2227 }
2252 if (FLAG_trace_profiler) { 2228 if (FLAG_trace_profiler) {
2253 OS::Print("Code Trie Root Count: E: %" Pd " I: %" Pd "\n", 2229 OS::Print("Code Trie Root Count: E: %" Pd " I: %" Pd "\n",
2254 code_trie_builder.exclusive_root()->count(), 2230 code_trie_builder.exclusive_root()->count(),
2255 code_trie_builder.inclusive_root()->count()); 2231 code_trie_builder.inclusive_root()->count());
2256 } 2232 }
2257 ProfileFunctionTrieBuilder function_trie_builder(isolate, 2233 ProfileFunctionTrieBuilder function_trie_builder(&live_code_table,
2258 &live_code_table,
2259 &dead_code_table, 2234 &dead_code_table,
2260 &tag_code_table, 2235 &tag_code_table,
2261 &function_table); 2236 &function_table);
2262 function_trie_builder.set_tag_order(tag_order); 2237 function_trie_builder.set_tag_order(tag_order);
2263 { 2238 {
2264 // Build ProfileFunction trie. 2239 // Build ProfileFunction trie.
2265 ScopeTimer sw("ProfileFunctionTrieBuilder", 2240 ScopeTimer sw("ProfileFunctionTrieBuilder::Build",
2266 FLAG_trace_profiler); 2241 FLAG_trace_profiler);
2267 sample_buffer->VisitSamples(&function_trie_builder); 2242 function_trie_builder.Build(processed_samples);
2268 function_trie_builder.exclusive_root()->SortByCount(); 2243 function_trie_builder.exclusive_root()->SortByCount();
2269 function_trie_builder.inclusive_root()->SortByCount(); 2244 function_trie_builder.inclusive_root()->SortByCount();
2270 } 2245 }
2271 if (FLAG_trace_profiler) { 2246 if (FLAG_trace_profiler) {
2272 OS::Print("Function Trie Root Count: E: %" Pd " I: %" Pd "\n", 2247 OS::Print("Function Trie Root Count: E: %" Pd " I: %" Pd "\n",
2273 function_trie_builder.exclusive_root()->count(), 2248 function_trie_builder.exclusive_root()->count(),
2274 function_trie_builder.inclusive_root()->count()); 2249 function_trie_builder.inclusive_root()->count());
2275 } 2250 }
2276 { 2251 {
2277 ScopeTimer sw("CpuProfileJSONStream", FLAG_trace_profiler); 2252 ScopeTimer sw("CpuProfileJSONStream", FLAG_trace_profiler);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2362 ASSERT(sample_buffer != NULL); 2337 ASSERT(sample_buffer != NULL);
2363 2338
2364 ClearProfileVisitor clear_profile(isolate); 2339 ClearProfileVisitor clear_profile(isolate);
2365 sample_buffer->VisitSamples(&clear_profile); 2340 sample_buffer->VisitSamples(&clear_profile);
2366 2341
2367 // Enable profile interrupts. 2342 // Enable profile interrupts.
2368 Profiler::BeginExecution(isolate); 2343 Profiler::BeginExecution(isolate);
2369 } 2344 }
2370 2345
2371 } // namespace dart 2346 } // namespace dart
OLDNEW
« runtime/vm/profiler.h ('K') | « runtime/vm/profiler.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698