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