| 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 |