Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(251)

Side by Side Diff: runtime/vm/profiler_service.cc

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

Powered by Google App Engine
This is Rietveld 408576698