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