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