| OLD | NEW |
| 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" |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |