OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 "platform/utils.h" | 5 #include "platform/utils.h" |
6 | 6 |
7 #include "vm/allocation.h" | 7 #include "vm/allocation.h" |
8 #include "vm/atomic.h" | 8 #include "vm/atomic.h" |
9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 } | 559 } |
560 PrintCollectedCode(&obj); | 560 PrintCollectedCode(&obj); |
561 } else if (kind() == kReusedCode) { | 561 } else if (kind() == kReusedCode) { |
562 if (name() == NULL) { | 562 if (name() == NULL) { |
563 // Lazily set generated name. | 563 // Lazily set generated name. |
564 GenerateAndSetSymbolName("[Reused]"); | 564 GenerateAndSetSymbolName("[Reused]"); |
565 } | 565 } |
566 PrintOverwrittenCode(&obj); | 566 PrintOverwrittenCode(&obj); |
567 } else if (kind() == kTagCode) { | 567 } else if (kind() == kTagCode) { |
568 if (name() == NULL) { | 568 if (name() == NULL) { |
569 const char* tag_name = start() == 0 ? "root" : VMTag::TagName(start()); | 569 if (UserTags::IsUserTag(start())) { |
570 ASSERT(tag_name != NULL); | 570 const char* tag_name = UserTags::TagName(start()); |
571 SetName(tag_name); | 571 ASSERT(tag_name != NULL); |
| 572 SetName(tag_name); |
| 573 } else if (VMTag::IsVMTag(start()) || |
| 574 VMTag::IsRuntimeEntryTag(start()) || |
| 575 VMTag::IsNativeEntryTag(start())) { |
| 576 const char* tag_name = VMTag::TagName(start()); |
| 577 ASSERT(tag_name != NULL); |
| 578 SetName(tag_name); |
| 579 } else { |
| 580 ASSERT(start() == 0); |
| 581 SetName("root"); |
| 582 } |
572 } | 583 } |
573 PrintTagCode(&obj); | 584 PrintTagCode(&obj); |
574 } else { | 585 } else { |
575 ASSERT(kind() == kNativeCode); | 586 ASSERT(kind() == kNativeCode); |
576 if (name() == NULL) { | 587 if (name() == NULL) { |
577 // Lazily set generated name. | 588 // Lazily set generated name. |
578 GenerateAndSetSymbolName("[Native]"); | 589 GenerateAndSetSymbolName("[Native]"); |
579 } | 590 } |
580 PrintNativeCode(&obj); | 591 PrintNativeCode(&obj); |
581 } | 592 } |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
927 if (timestamp < min_time_) { | 938 if (timestamp < min_time_) { |
928 min_time_ = timestamp; | 939 min_time_ = timestamp; |
929 } | 940 } |
930 // Make sure VM tag is created. | 941 // Make sure VM tag is created. |
931 if (VMTag::IsNativeEntryTag(sample->vm_tag())) { | 942 if (VMTag::IsNativeEntryTag(sample->vm_tag())) { |
932 CreateTag(VMTag::kNativeTagId); | 943 CreateTag(VMTag::kNativeTagId); |
933 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { | 944 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { |
934 CreateTag(VMTag::kRuntimeTagId); | 945 CreateTag(VMTag::kRuntimeTagId); |
935 } | 946 } |
936 CreateTag(sample->vm_tag()); | 947 CreateTag(sample->vm_tag()); |
| 948 // Make sure user tag is created. |
| 949 CreateUserTag(sample->user_tag()); |
937 // Exclusive tick for bottom frame. | 950 // Exclusive tick for bottom frame. |
938 Tick(sample->At(0), true, timestamp); | 951 Tick(sample->At(0), true, timestamp); |
939 // Inclusive tick for all frames. | 952 // Inclusive tick for all frames. |
940 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { | 953 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { |
941 if (sample->At(i) == 0) { | 954 if (sample->At(i) == 0) { |
942 break; | 955 break; |
943 } | 956 } |
944 frames_++; | 957 frames_++; |
945 Tick(sample->At(i), false, timestamp); | 958 Tick(sample->At(i), false, timestamp); |
946 } | 959 } |
(...skipping 15 matching lines...) Expand all Loading... |
962 } | 975 } |
963 CodeRegion* region = new CodeRegion(CodeRegion::kTagCode, | 976 CodeRegion* region = new CodeRegion(CodeRegion::kTagCode, |
964 tag, | 977 tag, |
965 tag + 1, | 978 tag + 1, |
966 0); | 979 0); |
967 index = tag_code_table_->InsertCodeRegion(region); | 980 index = tag_code_table_->InsertCodeRegion(region); |
968 ASSERT(index >= 0); | 981 ASSERT(index >= 0); |
969 region->set_creation_serial(visited()); | 982 region->set_creation_serial(visited()); |
970 } | 983 } |
971 | 984 |
| 985 void CreateUserTag(uword tag) { |
| 986 if (tag == 0) { |
| 987 // None set. |
| 988 return; |
| 989 } |
| 990 intptr_t index = tag_code_table_->FindIndex(tag); |
| 991 if (index >= 0) { |
| 992 // Already created. |
| 993 return; |
| 994 } |
| 995 CodeRegion* region = new CodeRegion(CodeRegion::kTagCode, |
| 996 tag, |
| 997 tag + 1, |
| 998 0); |
| 999 index = tag_code_table_->InsertCodeRegion(region); |
| 1000 ASSERT(index >= 0); |
| 1001 region->set_creation_serial(visited()); |
| 1002 } |
| 1003 |
972 void Tick(uword pc, bool exclusive, int64_t timestamp) { | 1004 void Tick(uword pc, bool exclusive, int64_t timestamp) { |
973 CodeRegionTable::TickResult r; | 1005 CodeRegionTable::TickResult r; |
974 intptr_t serial = exclusive ? -1 : visited(); | 1006 intptr_t serial = exclusive ? -1 : visited(); |
975 r = live_code_table_->Tick(pc, exclusive, serial, timestamp); | 1007 r = live_code_table_->Tick(pc, exclusive, serial, timestamp); |
976 if (r == CodeRegionTable::kTicked) { | 1008 if (r == CodeRegionTable::kTicked) { |
977 // Live code found and ticked. | 1009 // Live code found and ticked. |
978 return; | 1010 return; |
979 } | 1011 } |
980 if (r == CodeRegionTable::kNewerCode) { | 1012 if (r == CodeRegionTable::kNewerCode) { |
981 // Code has been overwritten by newer code. | 1013 // Code has been overwritten by newer code. |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 root_ = new CodeRegionTrieNode(tag_code_table_offset_ + root_index); | 1133 root_ = new CodeRegionTrieNode(tag_code_table_offset_ + root_index); |
1102 // Use tags by default. | 1134 // Use tags by default. |
1103 set_use_tags(true); | 1135 set_use_tags(true); |
1104 } | 1136 } |
1105 | 1137 |
1106 void VisitSample(Sample* sample) { | 1138 void VisitSample(Sample* sample) { |
1107 // Give the root a tick. | 1139 // Give the root a tick. |
1108 root_->Tick(); | 1140 root_->Tick(); |
1109 CodeRegionTrieNode* current = root_; | 1141 CodeRegionTrieNode* current = root_; |
1110 if (use_tags()) { | 1142 if (use_tags()) { |
| 1143 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); |
| 1144 if (user_tag_index >= 0) { |
| 1145 current = current->GetChild(user_tag_index); |
| 1146 // Give the tag a tick. |
| 1147 current->Tick(); |
| 1148 } |
1111 if (VMTag::IsNativeEntryTag(sample->vm_tag())) { | 1149 if (VMTag::IsNativeEntryTag(sample->vm_tag())) { |
1112 // Insert a dummy kNativeTagId node. | 1150 // Insert a dummy kNativeTagId node. |
1113 intptr_t tag_index = FindTagIndex(VMTag::kNativeTagId); | 1151 intptr_t tag_index = FindTagIndex(VMTag::kNativeTagId); |
1114 current = current->GetChild(tag_index); | 1152 current = current->GetChild(tag_index); |
1115 // Give the tag a tick. | 1153 // Give the tag a tick. |
1116 current->Tick(); | 1154 current->Tick(); |
1117 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { | 1155 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { |
1118 // Insert a dummy kRuntimeTagId node. | 1156 // Insert a dummy kRuntimeTagId node. |
1119 intptr_t tag_index = FindTagIndex(VMTag::kRuntimeTagId); | 1157 intptr_t tag_index = FindTagIndex(VMTag::kRuntimeTagId); |
1120 current = current->GetChild(tag_index); | 1158 current = current->GetChild(tag_index); |
(...skipping 23 matching lines...) Expand all Loading... |
1144 bool use_tags() const { | 1182 bool use_tags() const { |
1145 return use_tags_; | 1183 return use_tags_; |
1146 } | 1184 } |
1147 | 1185 |
1148 void set_use_tags(bool use_tags) { | 1186 void set_use_tags(bool use_tags) { |
1149 use_tags_ = use_tags; | 1187 use_tags_ = use_tags; |
1150 } | 1188 } |
1151 | 1189 |
1152 private: | 1190 private: |
1153 intptr_t FindTagIndex(uword tag) const { | 1191 intptr_t FindTagIndex(uword tag) const { |
| 1192 if (tag == 0) { |
| 1193 return -1; |
| 1194 } |
1154 intptr_t index = tag_code_table_->FindIndex(tag); | 1195 intptr_t index = tag_code_table_->FindIndex(tag); |
| 1196 if (index <= 0) { |
| 1197 return -1; |
| 1198 } |
1155 ASSERT(index >= 0); | 1199 ASSERT(index >= 0); |
1156 ASSERT((tag_code_table_->At(index))->contains(tag)); | 1200 ASSERT((tag_code_table_->At(index))->contains(tag)); |
1157 return tag_code_table_offset_ + index; | 1201 return tag_code_table_offset_ + index; |
1158 } | 1202 } |
1159 | 1203 |
1160 intptr_t FindFinalIndex(uword pc, int64_t timestamp) const { | 1204 intptr_t FindFinalIndex(uword pc, int64_t timestamp) const { |
1161 intptr_t index = live_code_table_->FindIndex(pc); | 1205 intptr_t index = live_code_table_->FindIndex(pc); |
1162 ASSERT(index >= 0); | 1206 ASSERT(index >= 0); |
1163 CodeRegion* region = live_code_table_->At(index); | 1207 CodeRegion* region = live_code_table_->At(index); |
1164 ASSERT(region->contains(pc)); | 1208 ASSERT(region->contains(pc)); |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1516 // The stack pointer gives us a better lower bound than | 1560 // The stack pointer gives us a better lower bound than |
1517 // the isolates stack limit. | 1561 // the isolates stack limit. |
1518 lower_bound_ = original_sp_; | 1562 lower_bound_ = original_sp_; |
1519 } | 1563 } |
1520 int i = 0; | 1564 int i = 0; |
1521 for (; i < FLAG_profile_depth; i++) { | 1565 for (; i < FLAG_profile_depth; i++) { |
1522 if (FLAG_profile_verify_stack_walk) { | 1566 if (FLAG_profile_verify_stack_walk) { |
1523 VerifyCodeAddress(heap, i, reinterpret_cast<uword>(pc)); | 1567 VerifyCodeAddress(heap, i, reinterpret_cast<uword>(pc)); |
1524 } | 1568 } |
1525 sample_->SetAt(i, reinterpret_cast<uword>(pc)); | 1569 sample_->SetAt(i, reinterpret_cast<uword>(pc)); |
| 1570 if (fp == NULL) { |
| 1571 return i + 1; |
| 1572 } |
1526 if (!ValidFramePointer(fp)) { | 1573 if (!ValidFramePointer(fp)) { |
1527 return i + 1; | 1574 return i + 1; |
1528 } | 1575 } |
1529 pc = CallerPC(fp); | 1576 pc = CallerPC(fp); |
1530 previous_fp = fp; | 1577 previous_fp = fp; |
1531 fp = CallerFP(fp); | 1578 fp = CallerFP(fp); |
1532 intptr_t step = fp - previous_fp; | 1579 intptr_t step = fp - previous_fp; |
1533 if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) { | 1580 if (fp == NULL) { |
| 1581 return i + 1; |
| 1582 } |
| 1583 if ((step >= kMaxStep)) { |
1534 // Frame pointer step is too large. | 1584 // Frame pointer step is too large. |
| 1585 return i + 1; |
| 1586 } |
| 1587 if ((fp <= previous_fp)) { |
1535 // Frame pointer did not move to a higher address. | 1588 // Frame pointer did not move to a higher address. |
| 1589 return i + 1; |
| 1590 } |
| 1591 if (!ValidFramePointer(fp)) { |
1536 // Frame pointer is outside of isolate stack bounds. | 1592 // Frame pointer is outside of isolate stack bounds. |
1537 return i + 1; | 1593 return i + 1; |
1538 } | 1594 } |
1539 // Move the lower bound up. | 1595 // Move the lower bound up. |
1540 lower_bound_ = reinterpret_cast<uword>(fp); | 1596 lower_bound_ = reinterpret_cast<uword>(fp); |
1541 } | 1597 } |
1542 return i; | 1598 return i; |
1543 } | 1599 } |
1544 | 1600 |
1545 private: | 1601 private: |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1603 if (profiler_data == NULL) { | 1659 if (profiler_data == NULL) { |
1604 return; | 1660 return; |
1605 } | 1661 } |
1606 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); | 1662 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); |
1607 if (sample_buffer == NULL) { | 1663 if (sample_buffer == NULL) { |
1608 return; | 1664 return; |
1609 } | 1665 } |
1610 Sample* sample = sample_buffer->ReserveSample(); | 1666 Sample* sample = sample_buffer->ReserveSample(); |
1611 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); | 1667 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); |
1612 sample->set_vm_tag(isolate->vm_tag()); | 1668 sample->set_vm_tag(isolate->vm_tag()); |
| 1669 sample->set_user_tag(isolate->user_tag()); |
1613 if (FLAG_profile_native_stack) { | 1670 if (FLAG_profile_native_stack) { |
1614 // Collect native and Dart frames. | 1671 // Collect native and Dart frames. |
1615 uword stack_lower = 0; | 1672 uword stack_lower = 0; |
1616 uword stack_upper = 0; | 1673 uword stack_upper = 0; |
1617 isolate->GetStackBounds(&stack_lower, &stack_upper); | 1674 isolate->GetStackBounds(&stack_lower, &stack_upper); |
1618 if ((stack_lower == 0) || (stack_upper == 0)) { | 1675 if ((stack_lower == 0) || (stack_upper == 0)) { |
1619 stack_lower = 0; | 1676 stack_lower = 0; |
1620 stack_upper = 0; | 1677 stack_upper = 0; |
1621 } | 1678 } |
1622 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper, | 1679 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper, |
1623 state.pc, state.fp, state.sp); | 1680 state.pc, state.fp, state.sp); |
1624 stackWalker.walk(isolate->heap()); | 1681 stackWalker.walk(isolate->heap()); |
1625 } else { | 1682 } else { |
1626 if (isolate->top_exit_frame_info() != 0) { | 1683 if (isolate->top_exit_frame_info() != 0) { |
1627 ProfilerDartStackWalker stackWalker(sample); | 1684 ProfilerDartStackWalker stackWalker(sample); |
1628 stackWalker.walk(); | 1685 stackWalker.walk(); |
1629 } else { | 1686 } else { |
1630 // TODO(johnmccutchan): Support collecting only Dart frames with | 1687 // TODO(johnmccutchan): Support collecting only Dart frames with |
1631 // ProfilerNativeStackWalker. | 1688 // ProfilerNativeStackWalker. |
1632 } | 1689 } |
1633 } | 1690 } |
1634 } | 1691 } |
1635 | 1692 |
1636 } // namespace dart | 1693 } // namespace dart |
OLD | NEW |