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 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 } | 557 } |
558 PrintCollectedCode(&obj); | 558 PrintCollectedCode(&obj); |
559 } else if (kind() == kReusedCode) { | 559 } else if (kind() == kReusedCode) { |
560 if (name() == NULL) { | 560 if (name() == NULL) { |
561 // Lazily set generated name. | 561 // Lazily set generated name. |
562 GenerateAndSetSymbolName("[Reused]"); | 562 GenerateAndSetSymbolName("[Reused]"); |
563 } | 563 } |
564 PrintOverwrittenCode(&obj); | 564 PrintOverwrittenCode(&obj); |
565 } else if (kind() == kTagCode) { | 565 } else if (kind() == kTagCode) { |
566 if (name() == NULL) { | 566 if (name() == NULL) { |
567 const char* tag_name = start() == 0 ? "root" : VMTag::TagName(start()); | 567 if (VMTag::IsVMTag(start())) { |
568 ASSERT(tag_name != NULL); | 568 const char* tag_name = VMTag::TagName(start()); |
569 SetName(tag_name); | 569 ASSERT(tag_name != NULL); |
| 570 SetName(tag_name); |
| 571 } else if (start() != 0) { |
| 572 const char* tag_name = UserTagHelper::TagName(start()); |
| 573 ASSERT(tag_name != NULL); |
| 574 SetName(tag_name); |
| 575 } else { |
| 576 SetName("root"); |
| 577 } |
570 } | 578 } |
571 PrintTagCode(&obj); | 579 PrintTagCode(&obj); |
572 } else { | 580 } else { |
573 ASSERT(kind() == kNativeCode); | 581 ASSERT(kind() == kNativeCode); |
574 if (name() == NULL) { | 582 if (name() == NULL) { |
575 // Lazily set generated name. | 583 // Lazily set generated name. |
576 GenerateAndSetSymbolName("[Native]"); | 584 GenerateAndSetSymbolName("[Native]"); |
577 } | 585 } |
578 PrintNativeCode(&obj); | 586 PrintNativeCode(&obj); |
579 } | 587 } |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 void VisitSample(Sample* sample) { | 928 void VisitSample(Sample* sample) { |
921 int64_t timestamp = sample->timestamp(); | 929 int64_t timestamp = sample->timestamp(); |
922 if (timestamp > max_time_) { | 930 if (timestamp > max_time_) { |
923 max_time_ = timestamp; | 931 max_time_ = timestamp; |
924 } | 932 } |
925 if (timestamp < min_time_) { | 933 if (timestamp < min_time_) { |
926 min_time_ = timestamp; | 934 min_time_ = timestamp; |
927 } | 935 } |
928 // Make sure VM tag is created. | 936 // Make sure VM tag is created. |
929 CreateTag(sample->vm_tag()); | 937 CreateTag(sample->vm_tag()); |
| 938 // Make sure user tag is created. |
| 939 CreateUserTag(sample->user_tag()); |
930 // Exclusive tick for bottom frame. | 940 // Exclusive tick for bottom frame. |
931 Tick(sample->At(0), true, timestamp); | 941 Tick(sample->At(0), true, timestamp); |
932 // Inclusive tick for all frames. | 942 // Inclusive tick for all frames. |
933 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { | 943 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { |
934 if (sample->At(i) == 0) { | 944 if (sample->At(i) == 0) { |
935 break; | 945 break; |
936 } | 946 } |
937 frames_++; | 947 frames_++; |
938 Tick(sample->At(i), false, timestamp); | 948 Tick(sample->At(i), false, timestamp); |
939 } | 949 } |
(...skipping 15 matching lines...) Expand all Loading... |
955 } | 965 } |
956 CodeRegion* region = new CodeRegion(CodeRegion::kTagCode, | 966 CodeRegion* region = new CodeRegion(CodeRegion::kTagCode, |
957 tag, | 967 tag, |
958 tag + 1, | 968 tag + 1, |
959 0); | 969 0); |
960 index = tag_code_table_->InsertCodeRegion(region); | 970 index = tag_code_table_->InsertCodeRegion(region); |
961 ASSERT(index >= 0); | 971 ASSERT(index >= 0); |
962 region->set_creation_serial(visited()); | 972 region->set_creation_serial(visited()); |
963 } | 973 } |
964 | 974 |
| 975 void CreateUserTag(uword tag) { |
| 976 intptr_t index = tag_code_table_->FindIndex(tag); |
| 977 if (index >= 0) { |
| 978 // Already created. |
| 979 return; |
| 980 } |
| 981 CodeRegion* region = new CodeRegion(CodeRegion::kTagCode, |
| 982 tag, |
| 983 tag + 1, |
| 984 0); |
| 985 index = tag_code_table_->InsertCodeRegion(region); |
| 986 ASSERT(index >= 0); |
| 987 region->set_creation_serial(visited()); |
| 988 } |
| 989 |
965 void Tick(uword pc, bool exclusive, int64_t timestamp) { | 990 void Tick(uword pc, bool exclusive, int64_t timestamp) { |
966 CodeRegionTable::TickResult r; | 991 CodeRegionTable::TickResult r; |
967 intptr_t serial = exclusive ? -1 : visited(); | 992 intptr_t serial = exclusive ? -1 : visited(); |
968 r = live_code_table_->Tick(pc, exclusive, serial, timestamp); | 993 r = live_code_table_->Tick(pc, exclusive, serial, timestamp); |
969 if (r == CodeRegionTable::kTicked) { | 994 if (r == CodeRegionTable::kTicked) { |
970 // Live code found and ticked. | 995 // Live code found and ticked. |
971 return; | 996 return; |
972 } | 997 } |
973 if (r == CodeRegionTable::kNewerCode) { | 998 if (r == CodeRegionTable::kNewerCode) { |
974 // Code has been overwritten by newer code. | 999 // Code has been overwritten by newer code. |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1094 root_ = new CodeRegionTrieNode(tag_code_table_offset_ + root_index); | 1119 root_ = new CodeRegionTrieNode(tag_code_table_offset_ + root_index); |
1095 // Use tags by default. | 1120 // Use tags by default. |
1096 set_use_tags(true); | 1121 set_use_tags(true); |
1097 } | 1122 } |
1098 | 1123 |
1099 void VisitSample(Sample* sample) { | 1124 void VisitSample(Sample* sample) { |
1100 // Give the root a tick. | 1125 // Give the root a tick. |
1101 root_->Tick(); | 1126 root_->Tick(); |
1102 CodeRegionTrieNode* current = root_; | 1127 CodeRegionTrieNode* current = root_; |
1103 if (use_tags()) { | 1128 if (use_tags()) { |
1104 intptr_t tag_index = FindTagIndex(sample->vm_tag()); | 1129 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); |
1105 current = current->GetChild(tag_index); | 1130 if (user_tag_index >= 0) { |
| 1131 current = current->GetChild(user_tag_index); |
| 1132 // Give the tag a tick. |
| 1133 current->Tick(); |
| 1134 } |
| 1135 intptr_t vm_tag_index = FindTagIndex(sample->vm_tag()); |
| 1136 current = current->GetChild(vm_tag_index); |
1106 // Give the tag a tick. | 1137 // Give the tag a tick. |
1107 current->Tick(); | 1138 current->Tick(); |
1108 } | 1139 } |
1109 // Walk the sampled PCs. | 1140 // Walk the sampled PCs. |
1110 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { | 1141 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { |
1111 if (sample->At(i) == 0) { | 1142 if (sample->At(i) == 0) { |
1112 break; | 1143 break; |
1113 } | 1144 } |
1114 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp()); | 1145 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp()); |
1115 current = current->GetChild(index); | 1146 current = current->GetChild(index); |
1116 current->Tick(); | 1147 current->Tick(); |
1117 } | 1148 } |
1118 } | 1149 } |
1119 | 1150 |
1120 CodeRegionTrieNode* root() const { | 1151 CodeRegionTrieNode* root() const { |
1121 return root_; | 1152 return root_; |
1122 } | 1153 } |
1123 | 1154 |
1124 bool use_tags() const { | 1155 bool use_tags() const { |
1125 return use_tags_; | 1156 return use_tags_; |
1126 } | 1157 } |
1127 | 1158 |
1128 void set_use_tags(bool use_tags) { | 1159 void set_use_tags(bool use_tags) { |
1129 use_tags_ = use_tags; | 1160 use_tags_ = use_tags; |
1130 } | 1161 } |
1131 | 1162 |
1132 private: | 1163 private: |
1133 intptr_t FindTagIndex(uword tag) const { | 1164 intptr_t FindTagIndex(uword tag) const { |
1134 intptr_t index = tag_code_table_->FindIndex(tag); | 1165 intptr_t index = tag_code_table_->FindIndex(tag); |
| 1166 if (index <= 0) { |
| 1167 return -1; |
| 1168 } |
1135 ASSERT(index >= 0); | 1169 ASSERT(index >= 0); |
1136 ASSERT((tag_code_table_->At(index))->contains(tag)); | 1170 ASSERT((tag_code_table_->At(index))->contains(tag)); |
1137 return tag_code_table_offset_ + index; | 1171 return tag_code_table_offset_ + index; |
1138 } | 1172 } |
1139 | 1173 |
1140 intptr_t FindFinalIndex(uword pc, int64_t timestamp) const { | 1174 intptr_t FindFinalIndex(uword pc, int64_t timestamp) const { |
1141 intptr_t index = live_code_table_->FindIndex(pc); | 1175 intptr_t index = live_code_table_->FindIndex(pc); |
1142 ASSERT(index >= 0); | 1176 ASSERT(index >= 0); |
1143 CodeRegion* region = live_code_table_->At(index); | 1177 CodeRegion* region = live_code_table_->At(index); |
1144 ASSERT(region->contains(pc)); | 1178 ASSERT(region->contains(pc)); |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1424 uword sp) | 1458 uword sp) |
1425 : sample_(sample), | 1459 : sample_(sample), |
1426 stack_upper_(stack_upper), | 1460 stack_upper_(stack_upper), |
1427 original_pc_(pc), | 1461 original_pc_(pc), |
1428 original_fp_(fp), | 1462 original_fp_(fp), |
1429 original_sp_(sp), | 1463 original_sp_(sp), |
1430 lower_bound_(stack_lower) { | 1464 lower_bound_(stack_lower) { |
1431 ASSERT(sample_ != NULL); | 1465 ASSERT(sample_ != NULL); |
1432 } | 1466 } |
1433 | 1467 |
1434 int walk(Heap* heap, uword vm_tag) { | 1468 int walk(Heap* heap, uword vm_tag, uword user_tag) { |
1435 const intptr_t kMaxStep = 0x1000; // 4K. | 1469 const intptr_t kMaxStep = 0x1000; // 4K. |
1436 const bool kWalkStack = true; // Walk the stack. | 1470 const bool kWalkStack = true; // Walk the stack. |
1437 // Always store the exclusive PC. | 1471 // Always store the exclusive PC. |
1438 sample_->SetAt(0, original_pc_); | 1472 sample_->SetAt(0, original_pc_); |
1439 // Always store the vm tag. | 1473 // Always store the vm tag. |
1440 sample_->set_vm_tag(vm_tag); | 1474 sample_->set_vm_tag(vm_tag); |
| 1475 // Always store the user tag. |
| 1476 sample_->set_user_tag(user_tag); |
1441 if (!kWalkStack) { | 1477 if (!kWalkStack) { |
1442 // Not walking the stack, only took exclusive sample. | 1478 // Not walking the stack, only took exclusive sample. |
1443 return 1; | 1479 return 1; |
1444 } | 1480 } |
1445 uword* pc = reinterpret_cast<uword*>(original_pc_); | 1481 uword* pc = reinterpret_cast<uword*>(original_pc_); |
1446 uword* fp = reinterpret_cast<uword*>(original_fp_); | 1482 uword* fp = reinterpret_cast<uword*>(original_fp_); |
1447 uword* previous_fp = fp; | 1483 uword* previous_fp = fp; |
1448 if (original_sp_ > original_fp_) { | 1484 if (original_sp_ > original_fp_) { |
1449 // Stack pointer should not be above frame pointer. | 1485 // Stack pointer should not be above frame pointer. |
1450 return 1; | 1486 return 1; |
1451 } | 1487 } |
1452 intptr_t gap = original_fp_ - original_sp_; | 1488 intptr_t gap = original_fp_ - original_sp_; |
1453 if (gap >= kMaxStep) { | 1489 if (gap >= kMaxStep) { |
1454 // Gap between frame pointer and stack pointer is | 1490 // Gap between frame pointer and stack pointer is |
1455 // too large. | 1491 // too large. |
1456 return 1; | 1492 return 1; |
1457 } | 1493 } |
1458 if (original_sp_ < lower_bound_) { | 1494 if (original_sp_ < lower_bound_) { |
1459 // The stack pointer gives us a better lower bound than | 1495 // The stack pointer gives us a better lower bound than |
1460 // the isolates stack limit. | 1496 // the isolates stack limit. |
1461 lower_bound_ = original_sp_; | 1497 lower_bound_ = original_sp_; |
1462 } | 1498 } |
1463 int i = 0; | 1499 int i = 0; |
1464 for (; i < FLAG_profile_depth; i++) { | 1500 for (; i < FLAG_profile_depth; i++) { |
1465 if (FLAG_profile_verify_stack_walk) { | 1501 if (FLAG_profile_verify_stack_walk) { |
1466 VerifyCodeAddress(heap, i, reinterpret_cast<uword>(pc)); | 1502 VerifyCodeAddress(heap, i, reinterpret_cast<uword>(pc)); |
1467 } | 1503 } |
1468 sample_->SetAt(i, reinterpret_cast<uword>(pc)); | 1504 sample_->SetAt(i, reinterpret_cast<uword>(pc)); |
| 1505 if (fp == NULL) { |
| 1506 return i + 1; |
| 1507 } |
1469 if (!ValidFramePointer(fp)) { | 1508 if (!ValidFramePointer(fp)) { |
1470 return i + 1; | 1509 return i + 1; |
1471 } | 1510 } |
1472 pc = CallerPC(fp); | 1511 pc = CallerPC(fp); |
1473 previous_fp = fp; | 1512 previous_fp = fp; |
1474 fp = CallerFP(fp); | 1513 fp = CallerFP(fp); |
1475 intptr_t step = fp - previous_fp; | 1514 intptr_t step = fp - previous_fp; |
1476 if ((step >= kMaxStep) || (fp <= previous_fp) || !ValidFramePointer(fp)) { | 1515 if (fp == NULL) { |
| 1516 return i + 1; |
| 1517 } |
| 1518 if ((step >= kMaxStep)) { |
1477 // Frame pointer step is too large. | 1519 // Frame pointer step is too large. |
| 1520 return i + 1; |
| 1521 } |
| 1522 if ((fp <= previous_fp)) { |
1478 // Frame pointer did not move to a higher address. | 1523 // Frame pointer did not move to a higher address. |
| 1524 return i + 1; |
| 1525 } |
| 1526 if (!ValidFramePointer(fp)) { |
1479 // Frame pointer is outside of isolate stack bounds. | 1527 // Frame pointer is outside of isolate stack bounds. |
1480 return i + 1; | 1528 return i + 1; |
1481 } | 1529 } |
1482 // Move the lower bound up. | 1530 // Move the lower bound up. |
1483 lower_bound_ = reinterpret_cast<uword>(fp); | 1531 lower_bound_ = reinterpret_cast<uword>(fp); |
1484 } | 1532 } |
1485 return i; | 1533 return i; |
1486 } | 1534 } |
1487 | 1535 |
1488 private: | 1536 private: |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1552 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); | 1600 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); |
1553 uword stack_lower = 0; | 1601 uword stack_lower = 0; |
1554 uword stack_upper = 0; | 1602 uword stack_upper = 0; |
1555 isolate->GetStackBounds(&stack_lower, &stack_upper); | 1603 isolate->GetStackBounds(&stack_lower, &stack_upper); |
1556 if ((stack_lower == 0) || (stack_upper == 0)) { | 1604 if ((stack_lower == 0) || (stack_upper == 0)) { |
1557 stack_lower = 0; | 1605 stack_lower = 0; |
1558 stack_upper = 0; | 1606 stack_upper = 0; |
1559 } | 1607 } |
1560 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, | 1608 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, |
1561 state.pc, state.fp, state.sp); | 1609 state.pc, state.fp, state.sp); |
1562 stackWalker.walk(isolate->heap(), isolate->vm_tag()); | 1610 stackWalker.walk(isolate->heap(), isolate->vm_tag(), isolate->user_tag()); |
1563 } | 1611 } |
1564 | 1612 |
1565 } // namespace dart | 1613 } // namespace dart |
OLD | NEW |