OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 "vm/profiler_service.h" | 5 #include "vm/profiler_service.h" |
6 | 6 |
7 #include "vm/growable_array.h" | 7 #include "vm/growable_array.h" |
8 #include "vm/hash_map.h" | 8 #include "vm/hash_map.h" |
9 #include "vm/log.h" | 9 #include "vm/log.h" |
10 #include "vm/malloc_hooks.h" | |
11 #include "vm/native_symbol.h" | 10 #include "vm/native_symbol.h" |
12 #include "vm/object.h" | 11 #include "vm/object.h" |
13 #include "vm/os.h" | 12 #include "vm/os.h" |
14 #include "vm/profiler.h" | 13 #include "vm/profiler.h" |
15 #include "vm/reusable_handles.h" | 14 #include "vm/reusable_handles.h" |
16 #include "vm/scope_timer.h" | 15 #include "vm/scope_timer.h" |
17 | 16 |
18 namespace dart { | 17 namespace dart { |
19 | 18 |
20 DECLARE_FLAG(int, max_profile_depth); | 19 DECLARE_FLAG(int, max_profile_depth); |
(...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 !b->Contains(a->start()) && !b->Contains(a->end() - 1)); | 856 !b->Contains(a->start()) && !b->Contains(a->end() - 1)); |
858 } | 857 } |
859 } | 858 } |
860 } | 859 } |
861 | 860 |
862 ZoneGrowableArray<ProfileCode*> table_; | 861 ZoneGrowableArray<ProfileCode*> table_; |
863 }; | 862 }; |
864 | 863 |
865 | 864 |
866 ProfileTrieNode::ProfileTrieNode(intptr_t table_index) | 865 ProfileTrieNode::ProfileTrieNode(intptr_t table_index) |
867 : table_index_(table_index), | 866 : table_index_(table_index), count_(0), children_(0), frame_id_(-1) { |
868 count_(0), | |
869 exclusive_allocations_(0), | |
870 inclusive_allocations_(0), | |
871 children_(0), | |
872 frame_id_(-1) { | |
873 ASSERT(table_index_ >= 0); | 867 ASSERT(table_index_ >= 0); |
874 } | 868 } |
875 | 869 |
876 | 870 |
877 ProfileTrieNode::~ProfileTrieNode() {} | 871 ProfileTrieNode::~ProfileTrieNode() {} |
878 | 872 |
879 | 873 |
880 void ProfileTrieNode::Tick(ProcessedSample* sample, bool exclusive) { | |
881 count_++; | |
882 IncrementAllocation(sample->native_allocation_size_bytes(), exclusive); | |
883 } | |
884 | |
885 | |
886 void ProfileTrieNode::SortChildren() { | 874 void ProfileTrieNode::SortChildren() { |
887 children_.Sort(ProfileTrieNodeCompare); | 875 children_.Sort(ProfileTrieNodeCompare); |
888 // Recurse. | 876 // Recurse. |
889 for (intptr_t i = 0; i < children_.length(); i++) { | 877 for (intptr_t i = 0; i < children_.length(); i++) { |
890 children_[i]->SortChildren(); | 878 children_[i]->SortChildren(); |
891 } | 879 } |
892 } | 880 } |
893 | 881 |
894 | 882 |
895 intptr_t ProfileTrieNode::IndexOf(ProfileTrieNode* node) { | 883 intptr_t ProfileTrieNode::IndexOf(ProfileTrieNode* node) { |
(...skipping 13 matching lines...) Expand all Loading... |
909 | 897 |
910 void PrintToJSONArray(JSONArray* array) const { | 898 void PrintToJSONArray(JSONArray* array) const { |
911 ASSERT(array != NULL); | 899 ASSERT(array != NULL); |
912 // Write CodeRegion index. | 900 // Write CodeRegion index. |
913 array->AddValue(table_index()); | 901 array->AddValue(table_index()); |
914 // Write count. | 902 // Write count. |
915 array->AddValue(count()); | 903 array->AddValue(count()); |
916 // Write number of children. | 904 // Write number of children. |
917 intptr_t child_count = NumChildren(); | 905 intptr_t child_count = NumChildren(); |
918 array->AddValue(child_count); | 906 array->AddValue(child_count); |
919 // Write inclusive allocations. | |
920 array->AddValue64(inclusive_allocations_); | |
921 // Write exclusive allocations. | |
922 array->AddValue64(exclusive_allocations_); | |
923 // Recurse. | 907 // Recurse. |
924 for (intptr_t i = 0; i < child_count; i++) { | 908 for (intptr_t i = 0; i < child_count; i++) { |
925 children_[i]->PrintToJSONArray(array); | 909 children_[i]->PrintToJSONArray(array); |
926 } | 910 } |
927 } | 911 } |
928 | 912 |
929 ProfileCodeTrieNode* GetChild(intptr_t child_table_index) { | 913 ProfileCodeTrieNode* GetChild(intptr_t child_table_index) { |
930 const intptr_t length = NumChildren(); | 914 const intptr_t length = NumChildren(); |
931 intptr_t i = 0; | 915 intptr_t i = 0; |
932 while (i < length) { | 916 while (i < length) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
974 public: | 958 public: |
975 explicit ProfileFunctionTrieNode(intptr_t table_index) | 959 explicit ProfileFunctionTrieNode(intptr_t table_index) |
976 : ProfileTrieNode(table_index), code_objects_(1) {} | 960 : ProfileTrieNode(table_index), code_objects_(1) {} |
977 | 961 |
978 void PrintToJSONArray(JSONArray* array) const { | 962 void PrintToJSONArray(JSONArray* array) const { |
979 ASSERT(array != NULL); | 963 ASSERT(array != NULL); |
980 // Write CodeRegion index. | 964 // Write CodeRegion index. |
981 array->AddValue(table_index()); | 965 array->AddValue(table_index()); |
982 // Write count. | 966 // Write count. |
983 array->AddValue(count()); | 967 array->AddValue(count()); |
984 // Write inclusive allocations. | |
985 array->AddValue64(inclusive_allocations_); | |
986 // Write exclusive allocations. | |
987 array->AddValue64(exclusive_allocations_); | |
988 // Write number of code objects. | 968 // Write number of code objects. |
989 intptr_t code_count = code_objects_.length(); | 969 intptr_t code_count = code_objects_.length(); |
990 array->AddValue(code_count); | 970 array->AddValue(code_count); |
991 // Write each code object index and ticks. | 971 // Write each code object index and ticks. |
992 for (intptr_t i = 0; i < code_count; i++) { | 972 for (intptr_t i = 0; i < code_count; i++) { |
993 array->AddValue(code_objects_[i].index()); | 973 array->AddValue(code_objects_[i].index()); |
994 array->AddValue(code_objects_[i].ticks()); | 974 array->AddValue(code_objects_[i].ticks()); |
995 } | 975 } |
996 // Write number of children. | 976 // Write number of children. |
997 intptr_t child_count = children_.length(); | 977 intptr_t child_count = children_.length(); |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1336 // and tick each one. | 1316 // and tick each one. |
1337 for (intptr_t frame_index = 0; frame_index < sample->length(); | 1317 for (intptr_t frame_index = 0; frame_index < sample->length(); |
1338 frame_index++) { | 1318 frame_index++) { |
1339 const uword pc = sample->At(frame_index); | 1319 const uword pc = sample->At(frame_index); |
1340 ASSERT(pc != 0); | 1320 ASSERT(pc != 0); |
1341 ProfileCode* code = FindOrRegisterProfileCode(pc, timestamp); | 1321 ProfileCode* code = FindOrRegisterProfileCode(pc, timestamp); |
1342 ASSERT(code != NULL); | 1322 ASSERT(code != NULL); |
1343 code->Tick(pc, IsExecutingFrame(sample, frame_index), sample_index); | 1323 code->Tick(pc, IsExecutingFrame(sample, frame_index), sample_index); |
1344 } | 1324 } |
1345 | 1325 |
1346 TickExitFrame(sample->vm_tag(), sample_index, sample); | 1326 TickExitFrame(sample->vm_tag(), sample_index); |
1347 } | 1327 } |
1348 SanitizeMinMaxTimes(); | 1328 SanitizeMinMaxTimes(); |
1349 } | 1329 } |
1350 | 1330 |
1351 void FinalizeCodeIndexes() { | 1331 void FinalizeCodeIndexes() { |
1352 ScopeTimer sw("ProfileBuilder::FinalizeCodeIndexes", FLAG_trace_profiler); | 1332 ScopeTimer sw("ProfileBuilder::FinalizeCodeIndexes", FLAG_trace_profiler); |
1353 ProfileCodeTable* live_table = profile_->live_code_; | 1333 ProfileCodeTable* live_table = profile_->live_code_; |
1354 ProfileCodeTable* dead_table = profile_->dead_code_; | 1334 ProfileCodeTable* dead_table = profile_->dead_code_; |
1355 ProfileCodeTable* tag_table = profile_->tag_code_; | 1335 ProfileCodeTable* tag_table = profile_->tag_code_; |
1356 const intptr_t dead_code_index_offset = live_table->length(); | 1336 const intptr_t dead_code_index_offset = live_table->length(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1422 | 1402 |
1423 void BuildInclusiveCodeTrie(ProfileCodeTrieNode* root) { | 1403 void BuildInclusiveCodeTrie(ProfileCodeTrieNode* root) { |
1424 ScopeTimer sw("ProfileBuilder::BuildInclusiveCodeTrie", | 1404 ScopeTimer sw("ProfileBuilder::BuildInclusiveCodeTrie", |
1425 FLAG_trace_profiler); | 1405 FLAG_trace_profiler); |
1426 for (intptr_t sample_index = 0; sample_index < samples_->length(); | 1406 for (intptr_t sample_index = 0; sample_index < samples_->length(); |
1427 sample_index++) { | 1407 sample_index++) { |
1428 ProcessedSample* sample = samples_->At(sample_index); | 1408 ProcessedSample* sample = samples_->At(sample_index); |
1429 | 1409 |
1430 // Tick the root. | 1410 // Tick the root. |
1431 ProfileCodeTrieNode* current = root; | 1411 ProfileCodeTrieNode* current = root; |
1432 current->Tick(sample); | 1412 current->Tick(); |
1433 | 1413 |
1434 // VM & User tags. | 1414 // VM & User tags. |
1435 current = | 1415 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); |
1436 AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); | |
1437 | 1416 |
1438 ResetKind(); | 1417 ResetKind(); |
1439 | 1418 |
1440 // Truncated tag. | 1419 // Truncated tag. |
1441 if (sample->truncated()) { | 1420 if (sample->truncated()) { |
1442 current = AppendTruncatedTag(current, sample); | 1421 current = AppendTruncatedTag(current); |
1443 } | 1422 } |
1444 | 1423 |
1445 // Walk the sampled PCs. | 1424 // Walk the sampled PCs. |
1446 Code& code = Code::Handle(); | 1425 Code& code = Code::Handle(); |
1447 for (intptr_t frame_index = sample->length() - 1; frame_index >= 0; | 1426 for (intptr_t frame_index = sample->length() - 1; frame_index >= 0; |
1448 frame_index--) { | 1427 frame_index--) { |
1449 ASSERT(sample->At(frame_index) != 0); | 1428 ASSERT(sample->At(frame_index) != 0); |
1450 intptr_t index = | 1429 intptr_t index = |
1451 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); | 1430 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); |
1452 ASSERT(index >= 0); | 1431 ASSERT(index >= 0); |
1453 ProfileCode* profile_code = | 1432 ProfileCode* profile_code = |
1454 GetProfileCode(sample->At(frame_index), sample->timestamp()); | 1433 GetProfileCode(sample->At(frame_index), sample->timestamp()); |
1455 ASSERT(profile_code->code_table_index() == index); | 1434 ASSERT(profile_code->code_table_index() == index); |
1456 code ^= profile_code->code(); | 1435 code ^= profile_code->code(); |
1457 current = AppendKind(code, current, sample); | 1436 current = AppendKind(code, current); |
1458 current = current->GetChild(index); | 1437 current = current->GetChild(index); |
1459 current->Tick(sample, (frame_index == 0)); | 1438 current->Tick(); |
1460 } | 1439 } |
1461 | 1440 |
1462 if (!sample->first_frame_executing()) { | 1441 if (!sample->first_frame_executing()) { |
1463 current = AppendExitFrame(sample->vm_tag(), current, sample); | 1442 current = AppendExitFrame(sample->vm_tag(), current); |
1464 } | 1443 } |
1465 } | 1444 } |
1466 } | 1445 } |
1467 | 1446 |
1468 void BuildExclusiveCodeTrie(ProfileCodeTrieNode* root) { | 1447 void BuildExclusiveCodeTrie(ProfileCodeTrieNode* root) { |
1469 ScopeTimer sw("ProfileBuilder::BuildExclusiveCodeTrie", | 1448 ScopeTimer sw("ProfileBuilder::BuildExclusiveCodeTrie", |
1470 FLAG_trace_profiler); | 1449 FLAG_trace_profiler); |
1471 for (intptr_t sample_index = 0; sample_index < samples_->length(); | 1450 for (intptr_t sample_index = 0; sample_index < samples_->length(); |
1472 sample_index++) { | 1451 sample_index++) { |
1473 ProcessedSample* sample = samples_->At(sample_index); | 1452 ProcessedSample* sample = samples_->At(sample_index); |
1474 | 1453 |
1475 // Tick the root. | 1454 // Tick the root. |
1476 ProfileCodeTrieNode* current = root; | 1455 ProfileCodeTrieNode* current = root; |
1477 current->Tick(sample); | 1456 current->Tick(); |
| 1457 |
1478 // VM & User tags. | 1458 // VM & User tags. |
1479 current = | 1459 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); |
1480 AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); | |
1481 | 1460 |
1482 ResetKind(); | 1461 ResetKind(); |
1483 | 1462 |
1484 if (!sample->first_frame_executing()) { | 1463 if (!sample->first_frame_executing()) { |
1485 current = AppendExitFrame(sample->vm_tag(), current, sample); | 1464 current = AppendExitFrame(sample->vm_tag(), current); |
1486 } | 1465 } |
1487 | 1466 |
1488 // Walk the sampled PCs. | 1467 // Walk the sampled PCs. |
1489 Code& code = Code::Handle(); | 1468 Code& code = Code::Handle(); |
1490 for (intptr_t frame_index = 0; frame_index < sample->length(); | 1469 for (intptr_t frame_index = 0; frame_index < sample->length(); |
1491 frame_index++) { | 1470 frame_index++) { |
1492 ASSERT(sample->At(frame_index) != 0); | 1471 ASSERT(sample->At(frame_index) != 0); |
1493 intptr_t index = | 1472 intptr_t index = |
1494 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); | 1473 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); |
1495 ASSERT(index >= 0); | 1474 ASSERT(index >= 0); |
1496 ProfileCode* profile_code = | 1475 ProfileCode* profile_code = |
1497 GetProfileCode(sample->At(frame_index), sample->timestamp()); | 1476 GetProfileCode(sample->At(frame_index), sample->timestamp()); |
1498 ASSERT(profile_code->code_table_index() == index); | 1477 ASSERT(profile_code->code_table_index() == index); |
1499 code ^= profile_code->code(); | 1478 code ^= profile_code->code(); |
1500 current = current->GetChild(index); | 1479 current = current->GetChild(index); |
1501 if (ShouldTickNode(sample, frame_index)) { | 1480 if (ShouldTickNode(sample, frame_index)) { |
1502 current->Tick(sample, (frame_index == 0)); | 1481 current->Tick(); |
1503 } | 1482 } |
1504 current = AppendKind(code, current, sample); | 1483 current = AppendKind(code, current); |
1505 } | 1484 } |
1506 // Truncated tag. | 1485 // Truncated tag. |
1507 if (sample->truncated()) { | 1486 if (sample->truncated()) { |
1508 current = AppendTruncatedTag(current, sample); | 1487 current = AppendTruncatedTag(current); |
1509 } | 1488 } |
1510 } | 1489 } |
1511 } | 1490 } |
1512 | 1491 |
1513 void BuildFunctionTrie(Profile::TrieKind kind) { | 1492 void BuildFunctionTrie(Profile::TrieKind kind) { |
1514 ProfileFunctionTrieNode* root = new ProfileFunctionTrieNode( | 1493 ProfileFunctionTrieNode* root = new ProfileFunctionTrieNode( |
1515 GetProfileFunctionTagIndex(VMTag::kRootTagId)); | 1494 GetProfileFunctionTagIndex(VMTag::kRootTagId)); |
1516 // We tick the functions while building the trie, but, we don't want to do | 1495 // We tick the functions while building the trie, but, we don't want to do |
1517 // it for both tries, just the exclusive trie. | 1496 // it for both tries, just the exclusive trie. |
1518 inclusive_tree_ = IsInclusiveTrie(kind); | 1497 inclusive_tree_ = IsInclusiveTrie(kind); |
(...skipping 10 matching lines...) Expand all Loading... |
1529 void BuildInclusiveFunctionTrie(ProfileFunctionTrieNode* root) { | 1508 void BuildInclusiveFunctionTrie(ProfileFunctionTrieNode* root) { |
1530 ScopeTimer sw("ProfileBuilder::BuildInclusiveFunctionTrie", | 1509 ScopeTimer sw("ProfileBuilder::BuildInclusiveFunctionTrie", |
1531 FLAG_trace_profiler); | 1510 FLAG_trace_profiler); |
1532 ASSERT(!tick_functions_); | 1511 ASSERT(!tick_functions_); |
1533 for (intptr_t sample_index = 0; sample_index < samples_->length(); | 1512 for (intptr_t sample_index = 0; sample_index < samples_->length(); |
1534 sample_index++) { | 1513 sample_index++) { |
1535 ProcessedSample* sample = samples_->At(sample_index); | 1514 ProcessedSample* sample = samples_->At(sample_index); |
1536 | 1515 |
1537 // Tick the root. | 1516 // Tick the root. |
1538 ProfileFunctionTrieNode* current = root; | 1517 ProfileFunctionTrieNode* current = root; |
1539 current->Tick(sample); | 1518 current->Tick(); |
| 1519 |
1540 // VM & User tags. | 1520 // VM & User tags. |
1541 current = | 1521 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); |
1542 AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); | |
1543 | 1522 |
1544 // Truncated tag. | 1523 // Truncated tag. |
1545 if (sample->truncated()) { | 1524 if (sample->truncated()) { |
1546 current = AppendTruncatedTag(current, sample); | 1525 current = AppendTruncatedTag(current); |
1547 } | 1526 } |
1548 | 1527 |
1549 // Walk the sampled PCs. | 1528 // Walk the sampled PCs. |
1550 for (intptr_t frame_index = sample->length() - 1; frame_index >= 0; | 1529 for (intptr_t frame_index = sample->length() - 1; frame_index >= 0; |
1551 frame_index--) { | 1530 frame_index--) { |
1552 ASSERT(sample->At(frame_index) != 0); | 1531 ASSERT(sample->At(frame_index) != 0); |
1553 current = ProcessFrame(current, sample_index, sample, frame_index); | 1532 current = ProcessFrame(current, sample_index, sample, frame_index); |
1554 } | 1533 } |
1555 | 1534 |
1556 if (!sample->first_frame_executing()) { | 1535 if (!sample->first_frame_executing()) { |
1557 current = AppendExitFrame(sample->vm_tag(), current, sample); | 1536 current = AppendExitFrame(sample->vm_tag(), current); |
1558 } | 1537 } |
1559 | 1538 |
1560 sample->set_timeline_trie(current); | 1539 sample->set_timeline_trie(current); |
1561 } | 1540 } |
1562 } | 1541 } |
1563 | 1542 |
1564 void BuildExclusiveFunctionTrie(ProfileFunctionTrieNode* root) { | 1543 void BuildExclusiveFunctionTrie(ProfileFunctionTrieNode* root) { |
1565 ScopeTimer sw("ProfileBuilder::BuildExclusiveFunctionTrie", | 1544 ScopeTimer sw("ProfileBuilder::BuildExclusiveFunctionTrie", |
1566 FLAG_trace_profiler); | 1545 FLAG_trace_profiler); |
1567 ASSERT(tick_functions_); | 1546 ASSERT(tick_functions_); |
1568 for (intptr_t sample_index = 0; sample_index < samples_->length(); | 1547 for (intptr_t sample_index = 0; sample_index < samples_->length(); |
1569 sample_index++) { | 1548 sample_index++) { |
1570 ProcessedSample* sample = samples_->At(sample_index); | 1549 ProcessedSample* sample = samples_->At(sample_index); |
1571 | 1550 |
1572 // Tick the root. | 1551 // Tick the root. |
1573 ProfileFunctionTrieNode* current = root; | 1552 ProfileFunctionTrieNode* current = root; |
1574 current->Tick(sample); | 1553 current->Tick(); |
| 1554 |
1575 // VM & User tags. | 1555 // VM & User tags. |
1576 current = | 1556 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); |
1577 AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); | |
1578 | 1557 |
1579 ResetKind(); | 1558 ResetKind(); |
1580 | 1559 |
1581 if (!sample->first_frame_executing()) { | 1560 if (!sample->first_frame_executing()) { |
1582 current = AppendExitFrame(sample->vm_tag(), current, sample); | 1561 current = AppendExitFrame(sample->vm_tag(), current); |
1583 } | 1562 } |
1584 | 1563 |
1585 // Walk the sampled PCs. | 1564 // Walk the sampled PCs. |
1586 for (intptr_t frame_index = 0; frame_index < sample->length(); | 1565 for (intptr_t frame_index = 0; frame_index < sample->length(); |
1587 frame_index++) { | 1566 frame_index++) { |
1588 ASSERT(sample->At(frame_index) != 0); | 1567 ASSERT(sample->At(frame_index) != 0); |
1589 current = ProcessFrame(current, sample_index, sample, frame_index); | 1568 current = ProcessFrame(current, sample_index, sample, frame_index); |
1590 } | 1569 } |
1591 | 1570 |
1592 TickExitFrameFunction(sample->vm_tag(), sample_index); | 1571 TickExitFrameFunction(sample->vm_tag(), sample_index); |
1593 | 1572 |
1594 // Truncated tag. | 1573 // Truncated tag. |
1595 if (sample->truncated()) { | 1574 if (sample->truncated()) { |
1596 current = AppendTruncatedTag(current, sample); | 1575 current = AppendTruncatedTag(current); |
1597 InclusiveTickTruncatedTag(sample); | 1576 InclusiveTickTruncatedTag(); |
1598 } | 1577 } |
1599 } | 1578 } |
1600 } | 1579 } |
1601 | 1580 |
1602 ProfileFunctionTrieNode* ProcessFrame(ProfileFunctionTrieNode* current, | 1581 ProfileFunctionTrieNode* ProcessFrame(ProfileFunctionTrieNode* current, |
1603 intptr_t sample_index, | 1582 intptr_t sample_index, |
1604 ProcessedSample* sample, | 1583 ProcessedSample* sample, |
1605 intptr_t frame_index) { | 1584 intptr_t frame_index) { |
1606 const uword pc = sample->At(frame_index); | 1585 const uword pc = sample->At(frame_index); |
1607 ProfileCode* profile_code = GetProfileCode(pc, sample->timestamp()); | 1586 ProfileCode* profile_code = GetProfileCode(pc, sample->timestamp()); |
(...skipping 17 matching lines...) Expand all Loading... |
1625 name.ToCString(), | 1604 name.ToCString(), |
1626 (*inlined_token_positions)[i].ToCString()); | 1605 (*inlined_token_positions)[i].ToCString()); |
1627 } | 1606 } |
1628 } | 1607 } |
1629 } | 1608 } |
1630 | 1609 |
1631 if (code.IsNull() || (inlined_functions == NULL) || | 1610 if (code.IsNull() || (inlined_functions == NULL) || |
1632 (inlined_functions->length() <= 1)) { | 1611 (inlined_functions->length() <= 1)) { |
1633 // No inlined functions. | 1612 // No inlined functions. |
1634 if (inclusive_tree_) { | 1613 if (inclusive_tree_) { |
1635 current = AppendKind(code, current, sample); | 1614 current = AppendKind(code, current); |
1636 } | 1615 } |
1637 current = ProcessFunction(current, sample_index, sample, frame_index, | 1616 current = ProcessFunction(current, sample_index, sample, frame_index, |
1638 function, token_position, code_index); | 1617 function, token_position, code_index); |
1639 if (!inclusive_tree_) { | 1618 if (!inclusive_tree_) { |
1640 current = AppendKind(code, current, sample); | 1619 current = AppendKind(code, current); |
1641 } | 1620 } |
1642 return current; | 1621 return current; |
1643 } | 1622 } |
1644 | 1623 |
1645 ASSERT(code.is_optimized()); | 1624 ASSERT(code.is_optimized()); |
1646 | 1625 |
1647 if (inclusive_tree_) { | 1626 if (inclusive_tree_) { |
1648 for (intptr_t i = 0; i < inlined_functions->length(); i++) { | 1627 for (intptr_t i = 0; i < inlined_functions->length(); i++) { |
1649 const Function* inlined_function = (*inlined_functions)[i]; | 1628 const Function* inlined_function = (*inlined_functions)[i]; |
1650 ASSERT(inlined_function != NULL); | 1629 ASSERT(inlined_function != NULL); |
1651 ASSERT(!inlined_function->IsNull()); | 1630 ASSERT(!inlined_function->IsNull()); |
1652 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; | 1631 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; |
1653 const bool inliner = i == 0; | 1632 const bool inliner = i == 0; |
1654 if (inliner) { | 1633 if (inliner) { |
1655 current = AppendKind(code, current, sample); | 1634 current = AppendKind(code, current); |
1656 } | 1635 } |
1657 current = ProcessInlinedFunction(current, sample_index, sample, | 1636 current = ProcessInlinedFunction(current, sample_index, sample, |
1658 frame_index, inlined_function, | 1637 frame_index, inlined_function, |
1659 inlined_token_position, code_index); | 1638 inlined_token_position, code_index); |
1660 if (inliner) { | 1639 if (inliner) { |
1661 current = AppendKind(kInlineStart, current, sample); | 1640 current = AppendKind(kInlineStart, current); |
1662 } | 1641 } |
1663 } | 1642 } |
1664 current = AppendKind(kInlineFinish, current, sample); | 1643 current = AppendKind(kInlineFinish, current); |
1665 } else { | 1644 } else { |
1666 // Append the inlined children. | 1645 // Append the inlined children. |
1667 current = AppendKind(kInlineFinish, current, sample); | 1646 current = AppendKind(kInlineFinish, current); |
1668 for (intptr_t i = inlined_functions->length() - 1; i >= 0; i--) { | 1647 for (intptr_t i = inlined_functions->length() - 1; i >= 0; i--) { |
1669 const Function* inlined_function = (*inlined_functions)[i]; | 1648 const Function* inlined_function = (*inlined_functions)[i]; |
1670 ASSERT(inlined_function != NULL); | 1649 ASSERT(inlined_function != NULL); |
1671 ASSERT(!inlined_function->IsNull()); | 1650 ASSERT(!inlined_function->IsNull()); |
1672 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; | 1651 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; |
1673 const bool inliner = i == 0; | 1652 const bool inliner = i == 0; |
1674 if (inliner) { | 1653 if (inliner) { |
1675 current = AppendKind(kInlineStart, current, sample); | 1654 current = AppendKind(kInlineStart, current); |
1676 } | 1655 } |
1677 current = ProcessInlinedFunction(current, sample_index, sample, | 1656 current = ProcessInlinedFunction(current, sample_index, sample, |
1678 frame_index + i, inlined_function, | 1657 frame_index + i, inlined_function, |
1679 inlined_token_position, code_index); | 1658 inlined_token_position, code_index); |
1680 if (inliner) { | 1659 if (inliner) { |
1681 current = AppendKind(code, current, sample); | 1660 current = AppendKind(code, current); |
1682 } | 1661 } |
1683 } | 1662 } |
1684 } | 1663 } |
1685 | 1664 |
1686 return current; | 1665 return current; |
1687 } | 1666 } |
1688 | 1667 |
1689 ProfileFunctionTrieNode* ProcessInlinedFunction( | 1668 ProfileFunctionTrieNode* ProcessInlinedFunction( |
1690 ProfileFunctionTrieNode* current, | 1669 ProfileFunctionTrieNode* current, |
1691 intptr_t sample_index, | 1670 intptr_t sample_index, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1726 THR_Print("S[%" Pd "]F[%" Pd "] %s %s 0x%" Px "\n", sample_index, | 1705 THR_Print("S[%" Pd "]F[%" Pd "] %s %s 0x%" Px "\n", sample_index, |
1727 frame_index, function->Name(), token_position.ToCString(), | 1706 frame_index, function->Name(), token_position.ToCString(), |
1728 sample->At(frame_index)); | 1707 sample->At(frame_index)); |
1729 } | 1708 } |
1730 function->Tick(IsExecutingFrame(sample, frame_index), sample_index, | 1709 function->Tick(IsExecutingFrame(sample, frame_index), sample_index, |
1731 token_position); | 1710 token_position); |
1732 } | 1711 } |
1733 function->AddProfileCode(code_index); | 1712 function->AddProfileCode(code_index); |
1734 current = current->GetChild(function->table_index()); | 1713 current = current->GetChild(function->table_index()); |
1735 if (ShouldTickNode(sample, frame_index)) { | 1714 if (ShouldTickNode(sample, frame_index)) { |
1736 current->Tick(sample, (frame_index == 0)); | 1715 current->Tick(); |
1737 } | 1716 } |
1738 current->AddCodeObjectIndex(code_index); | 1717 current->AddCodeObjectIndex(code_index); |
1739 return current; | 1718 return current; |
1740 } | 1719 } |
1741 | 1720 |
1742 // Tick the truncated tag's inclusive tick count. | 1721 // Tick the truncated tag's inclusive tick count. |
1743 void InclusiveTickTruncatedTag(ProcessedSample* sample) { | 1722 void InclusiveTickTruncatedTag() { |
1744 ProfileCodeTable* tag_table = profile_->tag_code_; | 1723 ProfileCodeTable* tag_table = profile_->tag_code_; |
1745 intptr_t index = tag_table->FindCodeIndexForPC(VMTag::kTruncatedTagId); | 1724 intptr_t index = tag_table->FindCodeIndexForPC(VMTag::kTruncatedTagId); |
1746 ASSERT(index >= 0); | 1725 ASSERT(index >= 0); |
1747 ProfileCode* code = tag_table->At(index); | 1726 ProfileCode* code = tag_table->At(index); |
1748 code->IncInclusiveTicks(); | 1727 code->IncInclusiveTicks(); |
1749 ASSERT(code != NULL); | 1728 ASSERT(code != NULL); |
1750 ProfileFunction* function = code->function(); | 1729 ProfileFunction* function = code->function(); |
1751 function->IncInclusiveTicks(); | 1730 function->IncInclusiveTicks(); |
1752 } | 1731 } |
1753 | 1732 |
1754 | 1733 |
1755 // Tag append functions are overloaded for |ProfileCodeTrieNode| and | 1734 // Tag append functions are overloaded for |ProfileCodeTrieNode| and |
1756 // |ProfileFunctionTrieNode| types. | 1735 // |ProfileFunctionTrieNode| types. |
1757 | 1736 |
1758 // ProfileCodeTrieNode | 1737 // ProfileCodeTrieNode |
1759 ProfileCodeTrieNode* AppendUserTag(uword user_tag, | 1738 ProfileCodeTrieNode* AppendUserTag(uword user_tag, |
1760 ProfileCodeTrieNode* current, | 1739 ProfileCodeTrieNode* current) { |
1761 ProcessedSample* sample) { | |
1762 intptr_t user_tag_index = GetProfileCodeTagIndex(user_tag); | 1740 intptr_t user_tag_index = GetProfileCodeTagIndex(user_tag); |
1763 if (user_tag_index >= 0) { | 1741 if (user_tag_index >= 0) { |
1764 current = current->GetChild(user_tag_index); | 1742 current = current->GetChild(user_tag_index); |
1765 current->Tick(sample); | 1743 current->Tick(); |
1766 } | 1744 } |
1767 return current; | 1745 return current; |
1768 } | 1746 } |
1769 | 1747 |
1770 ProfileCodeTrieNode* AppendTruncatedTag(ProfileCodeTrieNode* current, | 1748 ProfileCodeTrieNode* AppendTruncatedTag(ProfileCodeTrieNode* current) { |
1771 ProcessedSample* sample) { | |
1772 intptr_t truncated_tag_index = | 1749 intptr_t truncated_tag_index = |
1773 GetProfileCodeTagIndex(VMTag::kTruncatedTagId); | 1750 GetProfileCodeTagIndex(VMTag::kTruncatedTagId); |
1774 ASSERT(truncated_tag_index >= 0); | 1751 ASSERT(truncated_tag_index >= 0); |
1775 current = current->GetChild(truncated_tag_index); | 1752 current = current->GetChild(truncated_tag_index); |
1776 current->Tick(sample); | 1753 current->Tick(); |
1777 return current; | 1754 return current; |
1778 } | 1755 } |
1779 | 1756 |
1780 ProfileCodeTrieNode* AppendVMTag(uword vm_tag, | 1757 ProfileCodeTrieNode* AppendVMTag(uword vm_tag, ProfileCodeTrieNode* current) { |
1781 ProfileCodeTrieNode* current, | |
1782 ProcessedSample* sample) { | |
1783 if (VMTag::IsNativeEntryTag(vm_tag)) { | 1758 if (VMTag::IsNativeEntryTag(vm_tag)) { |
1784 // Insert a dummy kNativeTagId node. | 1759 // Insert a dummy kNativeTagId node. |
1785 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kNativeTagId); | 1760 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kNativeTagId); |
1786 current = current->GetChild(tag_index); | 1761 current = current->GetChild(tag_index); |
1787 // Give the tag a tick. | 1762 // Give the tag a tick. |
1788 current->Tick(sample); | 1763 current->Tick(); |
1789 } else if (VMTag::IsRuntimeEntryTag(vm_tag)) { | 1764 } else if (VMTag::IsRuntimeEntryTag(vm_tag)) { |
1790 // Insert a dummy kRuntimeTagId node. | 1765 // Insert a dummy kRuntimeTagId node. |
1791 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kRuntimeTagId); | 1766 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kRuntimeTagId); |
1792 current = current->GetChild(tag_index); | 1767 current = current->GetChild(tag_index); |
1793 // Give the tag a tick. | 1768 // Give the tag a tick. |
1794 current->Tick(sample); | 1769 current->Tick(); |
1795 } else { | 1770 } else { |
1796 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); | 1771 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); |
1797 current = current->GetChild(tag_index); | 1772 current = current->GetChild(tag_index); |
1798 // Give the tag a tick. | 1773 // Give the tag a tick. |
1799 current->Tick(sample); | 1774 current->Tick(); |
1800 } | 1775 } |
1801 return current; | 1776 return current; |
1802 } | 1777 } |
1803 | 1778 |
1804 ProfileCodeTrieNode* AppendSpecificNativeRuntimeEntryVMTag( | 1779 ProfileCodeTrieNode* AppendSpecificNativeRuntimeEntryVMTag( |
1805 uword vm_tag, | 1780 uword vm_tag, |
1806 ProfileCodeTrieNode* current, | 1781 ProfileCodeTrieNode* current) { |
1807 ProcessedSample* sample) { | |
1808 // Only Native and Runtime entries have a second VM tag. | 1782 // Only Native and Runtime entries have a second VM tag. |
1809 if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) { | 1783 if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) { |
1810 return current; | 1784 return current; |
1811 } | 1785 } |
1812 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); | 1786 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); |
1813 current = current->GetChild(tag_index); | 1787 current = current->GetChild(tag_index); |
1814 // Give the tag a tick. | 1788 // Give the tag a tick. |
1815 current->Tick(sample); | 1789 current->Tick(); |
1816 return current; | 1790 return current; |
1817 } | 1791 } |
1818 | 1792 |
1819 uword ProfileInfoKindToVMTag(ProfileInfoKind kind) { | 1793 uword ProfileInfoKindToVMTag(ProfileInfoKind kind) { |
1820 switch (kind) { | 1794 switch (kind) { |
1821 case kNone: | 1795 case kNone: |
1822 return VMTag::kNoneCodeTagId; | 1796 return VMTag::kNoneCodeTagId; |
1823 case kOptimized: | 1797 case kOptimized: |
1824 return VMTag::kOptimizedCodeTagId; | 1798 return VMTag::kOptimizedCodeTagId; |
1825 case kUnoptimized: | 1799 case kUnoptimized: |
1826 return VMTag::kUnoptimizedCodeTagId; | 1800 return VMTag::kUnoptimizedCodeTagId; |
1827 case kNative: | 1801 case kNative: |
1828 return VMTag::kNativeCodeTagId; | 1802 return VMTag::kNativeCodeTagId; |
1829 case kInlineStart: | 1803 case kInlineStart: |
1830 return VMTag::kInlineStartCodeTagId; | 1804 return VMTag::kInlineStartCodeTagId; |
1831 case kInlineFinish: | 1805 case kInlineFinish: |
1832 return VMTag::kInlineEndCodeTagId; | 1806 return VMTag::kInlineEndCodeTagId; |
1833 default: | 1807 default: |
1834 UNIMPLEMENTED(); | 1808 UNIMPLEMENTED(); |
1835 return VMTag::kInvalidTagId; | 1809 return VMTag::kInvalidTagId; |
1836 } | 1810 } |
1837 } | 1811 } |
1838 | 1812 |
1839 ProfileCodeTrieNode* AppendKind(ProfileInfoKind kind, | 1813 ProfileCodeTrieNode* AppendKind(ProfileInfoKind kind, |
1840 ProfileCodeTrieNode* current, | 1814 ProfileCodeTrieNode* current) { |
1841 ProcessedSample* sample) { | |
1842 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { | 1815 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { |
1843 // Only emit if debug tags are requested. | 1816 // Only emit if debug tags are requested. |
1844 return current; | 1817 return current; |
1845 } | 1818 } |
1846 if (kind != info_kind_) { | 1819 if (kind != info_kind_) { |
1847 info_kind_ = kind; | 1820 info_kind_ = kind; |
1848 intptr_t tag_index = GetProfileCodeTagIndex(ProfileInfoKindToVMTag(kind)); | 1821 intptr_t tag_index = GetProfileCodeTagIndex(ProfileInfoKindToVMTag(kind)); |
1849 ASSERT(tag_index >= 0); | 1822 ASSERT(tag_index >= 0); |
1850 current = current->GetChild(tag_index); | 1823 current = current->GetChild(tag_index); |
1851 current->Tick(sample); | 1824 current->Tick(); |
1852 } | 1825 } |
1853 return current; | 1826 return current; |
1854 } | 1827 } |
1855 | 1828 |
1856 ProfileCodeTrieNode* AppendKind(const Code& code, | 1829 ProfileCodeTrieNode* AppendKind(const Code& code, |
1857 ProfileCodeTrieNode* current, | 1830 ProfileCodeTrieNode* current) { |
1858 ProcessedSample* sample) { | |
1859 if (code.IsNull()) { | 1831 if (code.IsNull()) { |
1860 return AppendKind(kNone, current, sample); | 1832 return AppendKind(kNone, current); |
1861 } else if (code.is_optimized()) { | 1833 } else if (code.is_optimized()) { |
1862 return AppendKind(kOptimized, current, sample); | 1834 return AppendKind(kOptimized, current); |
1863 } else { | 1835 } else { |
1864 return AppendKind(kUnoptimized, current, sample); | 1836 return AppendKind(kUnoptimized, current); |
1865 } | 1837 } |
1866 } | 1838 } |
1867 | 1839 |
1868 ProfileCodeTrieNode* AppendVMTags(uword vm_tag, | 1840 ProfileCodeTrieNode* AppendVMTags(uword vm_tag, |
1869 ProfileCodeTrieNode* current, | 1841 ProfileCodeTrieNode* current) { |
1870 ProcessedSample* sample) { | 1842 current = AppendVMTag(vm_tag, current); |
1871 current = AppendVMTag(vm_tag, current, sample); | 1843 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); |
1872 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); | |
1873 return current; | 1844 return current; |
1874 } | 1845 } |
1875 | 1846 |
1876 void TickExitFrame(uword vm_tag, intptr_t serial, ProcessedSample* sample) { | 1847 void TickExitFrame(uword vm_tag, intptr_t serial) { |
1877 if (FLAG_profile_vm) { | 1848 if (FLAG_profile_vm) { |
1878 return; | 1849 return; |
1879 } | 1850 } |
1880 if (!VMTag::IsExitFrameTag(vm_tag)) { | 1851 if (!VMTag::IsExitFrameTag(vm_tag)) { |
1881 return; | 1852 return; |
1882 } | 1853 } |
1883 ProfileCodeTable* tag_table = profile_->tag_code_; | 1854 ProfileCodeTable* tag_table = profile_->tag_code_; |
1884 ProfileCode* code = tag_table->FindCodeForPC(vm_tag); | 1855 ProfileCode* code = tag_table->FindCodeForPC(vm_tag); |
1885 ASSERT(code != NULL); | 1856 ASSERT(code != NULL); |
1886 code->Tick(vm_tag, true, serial); | 1857 code->Tick(vm_tag, true, serial); |
1887 } | 1858 } |
1888 | 1859 |
1889 void TickExitFrameFunction(uword vm_tag, intptr_t serial) { | 1860 void TickExitFrameFunction(uword vm_tag, intptr_t serial) { |
1890 if (FLAG_profile_vm) { | 1861 if (FLAG_profile_vm) { |
1891 return; | 1862 return; |
1892 } | 1863 } |
1893 if (!VMTag::IsExitFrameTag(vm_tag)) { | 1864 if (!VMTag::IsExitFrameTag(vm_tag)) { |
1894 return; | 1865 return; |
1895 } | 1866 } |
1896 ProfileCodeTable* tag_table = profile_->tag_code_; | 1867 ProfileCodeTable* tag_table = profile_->tag_code_; |
1897 ProfileCode* code = tag_table->FindCodeForPC(vm_tag); | 1868 ProfileCode* code = tag_table->FindCodeForPC(vm_tag); |
1898 ASSERT(code != NULL); | 1869 ASSERT(code != NULL); |
1899 ProfileFunction* function = code->function(); | 1870 ProfileFunction* function = code->function(); |
1900 ASSERT(function != NULL); | 1871 ASSERT(function != NULL); |
1901 function->Tick(true, serial, TokenPosition::kNoSource); | 1872 function->Tick(true, serial, TokenPosition::kNoSource); |
1902 } | 1873 } |
1903 | 1874 |
1904 ProfileCodeTrieNode* AppendExitFrame(uword vm_tag, | 1875 ProfileCodeTrieNode* AppendExitFrame(uword vm_tag, |
1905 ProfileCodeTrieNode* current, | 1876 ProfileCodeTrieNode* current) { |
1906 ProcessedSample* sample) { | |
1907 if (FLAG_profile_vm) { | 1877 if (FLAG_profile_vm) { |
1908 return current; | 1878 return current; |
1909 } | 1879 } |
1910 | 1880 |
1911 if (!VMTag::IsExitFrameTag(vm_tag)) { | 1881 if (!VMTag::IsExitFrameTag(vm_tag)) { |
1912 return current; | 1882 return current; |
1913 } | 1883 } |
1914 | 1884 |
1915 if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) { | 1885 if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) { |
1916 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); | 1886 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); |
1917 } else { | 1887 } else { |
1918 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); | 1888 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); |
1919 current = current->GetChild(tag_index); | 1889 current = current->GetChild(tag_index); |
1920 // Give the tag a tick. | 1890 // Give the tag a tick. |
1921 current->Tick(sample); | 1891 current->Tick(); |
1922 } | 1892 } |
1923 return current; | 1893 return current; |
1924 } | 1894 } |
1925 | 1895 |
1926 ProfileCodeTrieNode* AppendTags(uword vm_tag, | 1896 ProfileCodeTrieNode* AppendTags(uword vm_tag, |
1927 uword user_tag, | 1897 uword user_tag, |
1928 ProfileCodeTrieNode* current, | 1898 ProfileCodeTrieNode* current) { |
1929 ProcessedSample* sample) { | |
1930 if (FLAG_profile_vm) { | 1899 if (FLAG_profile_vm) { |
1931 // None. | 1900 // None. |
1932 if (tag_order() == Profile::kNoTags) { | 1901 if (tag_order() == Profile::kNoTags) { |
1933 return current; | 1902 return current; |
1934 } | 1903 } |
1935 // User first. | 1904 // User first. |
1936 if ((tag_order() == Profile::kUserVM) || | 1905 if ((tag_order() == Profile::kUserVM) || |
1937 (tag_order() == Profile::kUser)) { | 1906 (tag_order() == Profile::kUser)) { |
1938 current = AppendUserTag(user_tag, current, sample); | 1907 current = AppendUserTag(user_tag, current); |
1939 // Only user. | 1908 // Only user. |
1940 if (tag_order() == Profile::kUser) { | 1909 if (tag_order() == Profile::kUser) { |
1941 return current; | 1910 return current; |
1942 } | 1911 } |
1943 return AppendVMTags(vm_tag, current, sample); | 1912 return AppendVMTags(vm_tag, current); |
1944 } | 1913 } |
1945 // VM first. | 1914 // VM first. |
1946 ASSERT((tag_order() == Profile::kVMUser) || | 1915 ASSERT((tag_order() == Profile::kVMUser) || |
1947 (tag_order() == Profile::kVM)); | 1916 (tag_order() == Profile::kVM)); |
1948 current = AppendVMTags(vm_tag, current, sample); | 1917 current = AppendVMTags(vm_tag, current); |
1949 // Only VM. | 1918 // Only VM. |
1950 if (tag_order() == Profile::kVM) { | 1919 if (tag_order() == Profile::kVM) { |
1951 return current; | 1920 return current; |
1952 } | 1921 } |
1953 return AppendUserTag(user_tag, current, sample); | 1922 return AppendUserTag(user_tag, current); |
1954 } | 1923 } |
1955 | 1924 |
1956 if (tag_order() == Profile::kNoTags) { | 1925 if (tag_order() == Profile::kNoTags) { |
1957 return current; | 1926 return current; |
1958 } | 1927 } |
1959 | 1928 |
1960 return AppendUserTag(user_tag, current, sample); | 1929 return AppendUserTag(user_tag, current); |
1961 } | 1930 } |
1962 | 1931 |
1963 // ProfileFunctionTrieNode | 1932 // ProfileFunctionTrieNode |
1964 void ResetKind() { info_kind_ = kNone; } | 1933 void ResetKind() { info_kind_ = kNone; } |
1965 | 1934 |
1966 ProfileFunctionTrieNode* AppendKind(ProfileInfoKind kind, | 1935 ProfileFunctionTrieNode* AppendKind(ProfileInfoKind kind, |
1967 ProfileFunctionTrieNode* current, | 1936 ProfileFunctionTrieNode* current) { |
1968 ProcessedSample* sample) { | |
1969 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { | 1937 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { |
1970 // Only emit if debug tags are requested. | 1938 // Only emit if debug tags are requested. |
1971 return current; | 1939 return current; |
1972 } | 1940 } |
1973 if (kind != info_kind_) { | 1941 if (kind != info_kind_) { |
1974 info_kind_ = kind; | 1942 info_kind_ = kind; |
1975 intptr_t tag_index = | 1943 intptr_t tag_index = |
1976 GetProfileFunctionTagIndex(ProfileInfoKindToVMTag(kind)); | 1944 GetProfileFunctionTagIndex(ProfileInfoKindToVMTag(kind)); |
1977 ASSERT(tag_index >= 0); | 1945 ASSERT(tag_index >= 0); |
1978 current = current->GetChild(tag_index); | 1946 current = current->GetChild(tag_index); |
1979 current->Tick(sample); | 1947 current->Tick(); |
1980 } | 1948 } |
1981 return current; | 1949 return current; |
1982 } | 1950 } |
1983 | 1951 |
1984 ProfileFunctionTrieNode* AppendKind(const Code& code, | 1952 ProfileFunctionTrieNode* AppendKind(const Code& code, |
1985 ProfileFunctionTrieNode* current, | 1953 ProfileFunctionTrieNode* current) { |
1986 ProcessedSample* sample) { | |
1987 if (code.IsNull()) { | 1954 if (code.IsNull()) { |
1988 return AppendKind(kNone, current, sample); | 1955 return AppendKind(kNone, current); |
1989 } else if (code.is_optimized()) { | 1956 } else if (code.is_optimized()) { |
1990 return AppendKind(kOptimized, current, sample); | 1957 return AppendKind(kOptimized, current); |
1991 } else { | 1958 } else { |
1992 return AppendKind(kUnoptimized, current, sample); | 1959 return AppendKind(kUnoptimized, current); |
1993 } | 1960 } |
1994 } | 1961 } |
1995 | 1962 |
1996 ProfileFunctionTrieNode* AppendUserTag(uword user_tag, | 1963 ProfileFunctionTrieNode* AppendUserTag(uword user_tag, |
1997 ProfileFunctionTrieNode* current, | 1964 ProfileFunctionTrieNode* current) { |
1998 ProcessedSample* sample) { | |
1999 intptr_t user_tag_index = GetProfileFunctionTagIndex(user_tag); | 1965 intptr_t user_tag_index = GetProfileFunctionTagIndex(user_tag); |
2000 if (user_tag_index >= 0) { | 1966 if (user_tag_index >= 0) { |
2001 current = current->GetChild(user_tag_index); | 1967 current = current->GetChild(user_tag_index); |
2002 current->Tick(sample); | 1968 current->Tick(); |
2003 } | 1969 } |
2004 return current; | 1970 return current; |
2005 } | 1971 } |
2006 | 1972 |
2007 ProfileFunctionTrieNode* AppendTruncatedTag(ProfileFunctionTrieNode* current, | 1973 ProfileFunctionTrieNode* AppendTruncatedTag( |
2008 ProcessedSample* sample) { | 1974 ProfileFunctionTrieNode* current) { |
2009 intptr_t truncated_tag_index = | 1975 intptr_t truncated_tag_index = |
2010 GetProfileFunctionTagIndex(VMTag::kTruncatedTagId); | 1976 GetProfileFunctionTagIndex(VMTag::kTruncatedTagId); |
2011 ASSERT(truncated_tag_index >= 0); | 1977 ASSERT(truncated_tag_index >= 0); |
2012 current = current->GetChild(truncated_tag_index); | 1978 current = current->GetChild(truncated_tag_index); |
2013 current->Tick(sample); | 1979 current->Tick(); |
2014 return current; | 1980 return current; |
2015 } | 1981 } |
2016 | 1982 |
2017 ProfileFunctionTrieNode* AppendVMTag(uword vm_tag, | 1983 ProfileFunctionTrieNode* AppendVMTag(uword vm_tag, |
2018 ProfileFunctionTrieNode* current, | 1984 ProfileFunctionTrieNode* current) { |
2019 ProcessedSample* sample) { | |
2020 if (VMTag::IsNativeEntryTag(vm_tag)) { | 1985 if (VMTag::IsNativeEntryTag(vm_tag)) { |
2021 // Insert a dummy kNativeTagId node. | 1986 // Insert a dummy kNativeTagId node. |
2022 intptr_t tag_index = GetProfileFunctionTagIndex(VMTag::kNativeTagId); | 1987 intptr_t tag_index = GetProfileFunctionTagIndex(VMTag::kNativeTagId); |
2023 current = current->GetChild(tag_index); | 1988 current = current->GetChild(tag_index); |
2024 // Give the tag a tick. | 1989 // Give the tag a tick. |
2025 current->Tick(sample); | 1990 current->Tick(); |
2026 } else if (VMTag::IsRuntimeEntryTag(vm_tag)) { | 1991 } else if (VMTag::IsRuntimeEntryTag(vm_tag)) { |
2027 // Insert a dummy kRuntimeTagId node. | 1992 // Insert a dummy kRuntimeTagId node. |
2028 intptr_t tag_index = GetProfileFunctionTagIndex(VMTag::kRuntimeTagId); | 1993 intptr_t tag_index = GetProfileFunctionTagIndex(VMTag::kRuntimeTagId); |
2029 current = current->GetChild(tag_index); | 1994 current = current->GetChild(tag_index); |
2030 // Give the tag a tick. | 1995 // Give the tag a tick. |
2031 current->Tick(sample); | 1996 current->Tick(); |
2032 } else { | 1997 } else { |
2033 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); | 1998 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); |
2034 current = current->GetChild(tag_index); | 1999 current = current->GetChild(tag_index); |
2035 // Give the tag a tick. | 2000 // Give the tag a tick. |
2036 current->Tick(sample); | 2001 current->Tick(); |
2037 } | 2002 } |
2038 return current; | 2003 return current; |
2039 } | 2004 } |
2040 | 2005 |
2041 ProfileFunctionTrieNode* AppendSpecificNativeRuntimeEntryVMTag( | 2006 ProfileFunctionTrieNode* AppendSpecificNativeRuntimeEntryVMTag( |
2042 uword vm_tag, | 2007 uword vm_tag, |
2043 ProfileFunctionTrieNode* current, | 2008 ProfileFunctionTrieNode* current) { |
2044 ProcessedSample* sample) { | |
2045 // Only Native and Runtime entries have a second VM tag. | 2009 // Only Native and Runtime entries have a second VM tag. |
2046 if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) { | 2010 if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) { |
2047 return current; | 2011 return current; |
2048 } | 2012 } |
2049 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); | 2013 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); |
2050 current = current->GetChild(tag_index); | 2014 current = current->GetChild(tag_index); |
2051 // Give the tag a tick. | 2015 // Give the tag a tick. |
2052 current->Tick(sample); | 2016 current->Tick(); |
2053 return current; | 2017 return current; |
2054 } | 2018 } |
2055 | 2019 |
2056 ProfileFunctionTrieNode* AppendVMTags(uword vm_tag, | 2020 ProfileFunctionTrieNode* AppendVMTags(uword vm_tag, |
2057 ProfileFunctionTrieNode* current, | 2021 ProfileFunctionTrieNode* current) { |
2058 ProcessedSample* sample) { | 2022 current = AppendVMTag(vm_tag, current); |
2059 current = AppendVMTag(vm_tag, current, sample); | 2023 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); |
2060 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); | |
2061 return current; | 2024 return current; |
2062 } | 2025 } |
2063 | 2026 |
2064 ProfileFunctionTrieNode* AppendExitFrame(uword vm_tag, | 2027 ProfileFunctionTrieNode* AppendExitFrame(uword vm_tag, |
2065 ProfileFunctionTrieNode* current, | 2028 ProfileFunctionTrieNode* current) { |
2066 ProcessedSample* sample) { | |
2067 if (FLAG_profile_vm) { | 2029 if (FLAG_profile_vm) { |
2068 return current; | 2030 return current; |
2069 } | 2031 } |
2070 | 2032 |
2071 if (!VMTag::IsExitFrameTag(vm_tag)) { | 2033 if (!VMTag::IsExitFrameTag(vm_tag)) { |
2072 return current; | 2034 return current; |
2073 } | 2035 } |
2074 if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) { | 2036 if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) { |
2075 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); | 2037 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); |
2076 } else { | 2038 } else { |
2077 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); | 2039 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); |
2078 current = current->GetChild(tag_index); | 2040 current = current->GetChild(tag_index); |
2079 // Give the tag a tick. | 2041 // Give the tag a tick. |
2080 current->Tick(sample); | 2042 current->Tick(); |
2081 } | 2043 } |
2082 return current; | 2044 return current; |
2083 } | 2045 } |
2084 | 2046 |
2085 ProfileFunctionTrieNode* AppendTags(uword vm_tag, | 2047 ProfileFunctionTrieNode* AppendTags(uword vm_tag, |
2086 uword user_tag, | 2048 uword user_tag, |
2087 ProfileFunctionTrieNode* current, | 2049 ProfileFunctionTrieNode* current) { |
2088 ProcessedSample* sample) { | |
2089 if (FLAG_profile_vm) { | 2050 if (FLAG_profile_vm) { |
2090 // None. | 2051 // None. |
2091 if (tag_order() == Profile::kNoTags) { | 2052 if (tag_order() == Profile::kNoTags) { |
2092 return current; | 2053 return current; |
2093 } | 2054 } |
2094 // User first. | 2055 // User first. |
2095 if ((tag_order() == Profile::kUserVM) || | 2056 if ((tag_order() == Profile::kUserVM) || |
2096 (tag_order() == Profile::kUser)) { | 2057 (tag_order() == Profile::kUser)) { |
2097 current = AppendUserTag(user_tag, current, sample); | 2058 current = AppendUserTag(user_tag, current); |
2098 // Only user. | 2059 // Only user. |
2099 if (tag_order() == Profile::kUser) { | 2060 if (tag_order() == Profile::kUser) { |
2100 return current; | 2061 return current; |
2101 } | 2062 } |
2102 return AppendVMTags(vm_tag, current, sample); | 2063 return AppendVMTags(vm_tag, current); |
2103 } | 2064 } |
2104 // VM first. | 2065 // VM first. |
2105 ASSERT((tag_order() == Profile::kVMUser) || | 2066 ASSERT((tag_order() == Profile::kVMUser) || |
2106 (tag_order() == Profile::kVM)); | 2067 (tag_order() == Profile::kVM)); |
2107 current = AppendVMTags(vm_tag, current, sample); | 2068 current = AppendVMTags(vm_tag, current); |
2108 // Only VM. | 2069 // Only VM. |
2109 if (tag_order() == Profile::kVM) { | 2070 if (tag_order() == Profile::kVM) { |
2110 return current; | 2071 return current; |
2111 } | 2072 } |
2112 return AppendUserTag(user_tag, current, sample); | 2073 return AppendUserTag(user_tag, current); |
2113 } | 2074 } |
2114 | 2075 |
2115 if (tag_order() == Profile::kNoTags) { | 2076 if (tag_order() == Profile::kNoTags) { |
2116 return current; | 2077 return current; |
2117 } | 2078 } |
2118 | 2079 |
2119 return AppendUserTag(user_tag, current, sample); | 2080 return AppendUserTag(user_tag, current); |
2120 } | 2081 } |
2121 | 2082 |
2122 intptr_t GetProfileCodeTagIndex(uword tag) { | 2083 intptr_t GetProfileCodeTagIndex(uword tag) { |
2123 ProfileCodeTable* tag_table = profile_->tag_code_; | 2084 ProfileCodeTable* tag_table = profile_->tag_code_; |
2124 intptr_t index = tag_table->FindCodeIndexForPC(tag); | 2085 intptr_t index = tag_table->FindCodeIndexForPC(tag); |
2125 ASSERT(index >= 0); | 2086 ASSERT(index >= 0); |
2126 ProfileCode* code = tag_table->At(index); | 2087 ProfileCode* code = tag_table->At(index); |
2127 ASSERT(code != NULL); | 2088 ASSERT(code != NULL); |
2128 return code->code_table_index(); | 2089 return code->code_table_index(); |
2129 } | 2090 } |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2592 return code->exclusive_ticks(); | 2553 return code->exclusive_ticks(); |
2593 } else { | 2554 } else { |
2594 ProfileFunction* func = profile_->GetFunction(current_->table_index()); | 2555 ProfileFunction* func = profile_->GetFunction(current_->table_index()); |
2595 return func->exclusive_ticks(); | 2556 return func->exclusive_ticks(); |
2596 } | 2557 } |
2597 UNREACHABLE(); | 2558 UNREACHABLE(); |
2598 return -1; | 2559 return -1; |
2599 } | 2560 } |
2600 | 2561 |
2601 | 2562 |
2602 intptr_t ProfileTrieWalker::CurrentInclusiveAllocations() { | |
2603 if (current_ == NULL) { | |
2604 return -1; | |
2605 } | |
2606 return current_->inclusive_allocations(); | |
2607 } | |
2608 | |
2609 | |
2610 intptr_t ProfileTrieWalker::CurrentExclusiveAllocations() { | |
2611 if (current_ == NULL) { | |
2612 return -1; | |
2613 } | |
2614 return current_->exclusive_allocations(); | |
2615 } | |
2616 | |
2617 | |
2618 const char* ProfileTrieWalker::CurrentToken() { | 2563 const char* ProfileTrieWalker::CurrentToken() { |
2619 if (current_ == NULL) { | 2564 if (current_ == NULL) { |
2620 return NULL; | 2565 return NULL; |
2621 } | 2566 } |
2622 if (code_trie_) { | 2567 if (code_trie_) { |
2623 return NULL; | 2568 return NULL; |
2624 } | 2569 } |
2625 ProfileFunction* func = profile_->GetFunction(current_->table_index()); | 2570 ProfileFunction* func = profile_->GetFunction(current_->table_index()); |
2626 const Function& function = *(func->function()); | 2571 const Function& function = *(func->function()); |
2627 if (function.IsNull()) { | 2572 if (function.IsNull()) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2773 bool FilterSample(Sample* sample) { | 2718 bool FilterSample(Sample* sample) { |
2774 return sample->is_allocation_sample() && | 2719 return sample->is_allocation_sample() && |
2775 (sample->allocation_cid() == cls_.id()); | 2720 (sample->allocation_cid() == cls_.id()); |
2776 } | 2721 } |
2777 | 2722 |
2778 private: | 2723 private: |
2779 const Class& cls_; | 2724 const Class& cls_; |
2780 }; | 2725 }; |
2781 | 2726 |
2782 | 2727 |
| 2728 class NativeAllocationSampleFilter : public SampleFilter { |
| 2729 public: |
| 2730 NativeAllocationSampleFilter(intptr_t thread_task_mask, |
| 2731 int64_t time_origin_micros, |
| 2732 int64_t time_extent_micros) |
| 2733 : SampleFilter(ILLEGAL_PORT, |
| 2734 thread_task_mask, |
| 2735 time_origin_micros, |
| 2736 time_extent_micros) {} |
| 2737 bool FilterSample(Sample* sample) { |
| 2738 return sample->is_native_allocation_sample(); |
| 2739 } |
| 2740 }; |
| 2741 |
| 2742 |
2783 void ProfilerService::PrintAllocationJSON(JSONStream* stream, | 2743 void ProfilerService::PrintAllocationJSON(JSONStream* stream, |
2784 Profile::TagOrder tag_order, | 2744 Profile::TagOrder tag_order, |
2785 const Class& cls, | 2745 const Class& cls, |
2786 int64_t time_origin_micros, | 2746 int64_t time_origin_micros, |
2787 int64_t time_extent_micros) { | 2747 int64_t time_extent_micros) { |
2788 Thread* thread = Thread::Current(); | 2748 Thread* thread = Thread::Current(); |
2789 Isolate* isolate = thread->isolate(); | 2749 Isolate* isolate = thread->isolate(); |
2790 ClassAllocationSampleFilter filter(isolate->main_port(), cls, | 2750 ClassAllocationSampleFilter filter(isolate->main_port(), cls, |
2791 Thread::kMutatorTask, time_origin_micros, | 2751 Thread::kMutatorTask, time_origin_micros, |
2792 time_extent_micros); | 2752 time_extent_micros); |
2793 const bool as_timeline = false; | 2753 const bool as_timeline = false; |
2794 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); | 2754 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); |
2795 } | 2755 } |
2796 | 2756 |
2797 | 2757 |
2798 void ProfilerService::PrintNativeAllocationJSON(JSONStream* stream, | 2758 void ProfilerService::PrintNativeAllocationJSON(JSONStream* stream, |
2799 Profile::TagOrder tag_order, | 2759 Profile::TagOrder tag_order, |
2800 int64_t time_origin_micros, | 2760 int64_t time_origin_micros, |
2801 int64_t time_extent_micros) { | 2761 int64_t time_extent_micros) { |
2802 Thread* thread = Thread::Current(); | 2762 Thread* thread = Thread::Current(); |
2803 NativeAllocationSampleFilter filter(time_origin_micros, time_extent_micros); | 2763 const intptr_t thread_task_mask = Thread::kMutatorTask | |
| 2764 Thread::kCompilerTask | |
| 2765 Thread::kSweeperTask | Thread::kMarkerTask; |
| 2766 NativeAllocationSampleFilter filter(thread_task_mask, time_origin_micros, |
| 2767 time_extent_micros); |
2804 const bool as_timeline = false; | 2768 const bool as_timeline = false; |
2805 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); | 2769 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); |
2806 } | 2770 } |
2807 | 2771 |
2808 | 2772 |
2809 void ProfilerService::PrintTimelineJSON(JSONStream* stream, | 2773 void ProfilerService::PrintTimelineJSON(JSONStream* stream, |
2810 Profile::TagOrder tag_order, | 2774 Profile::TagOrder tag_order, |
2811 int64_t time_origin_micros, | 2775 int64_t time_origin_micros, |
2812 int64_t time_extent_micros) { | 2776 int64_t time_extent_micros) { |
2813 Thread* thread = Thread::Current(); | 2777 Thread* thread = Thread::Current(); |
(...skipping 20 matching lines...) Expand all Loading... |
2834 // Disable thread interrupts while processing the buffer. | 2798 // Disable thread interrupts while processing the buffer. |
2835 DisableThreadInterruptsScope dtis(thread); | 2799 DisableThreadInterruptsScope dtis(thread); |
2836 | 2800 |
2837 ClearProfileVisitor clear_profile(isolate); | 2801 ClearProfileVisitor clear_profile(isolate); |
2838 sample_buffer->VisitSamples(&clear_profile); | 2802 sample_buffer->VisitSamples(&clear_profile); |
2839 } | 2803 } |
2840 | 2804 |
2841 #endif // !PRODUCT | 2805 #endif // !PRODUCT |
2842 | 2806 |
2843 } // namespace dart | 2807 } // namespace dart |
OLD | NEW |