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

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

Issue 2771293003: Resubmission of native memory allocation info surfacing in Observatory. Fixed crashing tests and st… (Closed)
Patch Set: Added page to Observatory to display native memory allocation information. 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 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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