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

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

Issue 1014473006: Profiler fixes for 1.9 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 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 | Annotate | Revision Log
« no previous file with comments | « runtime/observatory/lib/src/elements/cpu_profile.html ('k') | no next file » | 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/native_symbol.h" 8 #include "vm/native_symbol.h"
9 #include "vm/object.h" 9 #include "vm/object.h"
10 #include "vm/os.h" 10 #include "vm/os.h"
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 if ((*code_objects_)[i] == index) { 167 if ((*code_objects_)[i] == index) {
168 return; 168 return;
169 } 169 }
170 } 170 }
171 code_objects_->Add(index); 171 code_objects_->Add(index);
172 } 172 }
173 173
174 intptr_t inclusive_ticks() const { 174 intptr_t inclusive_ticks() const {
175 return inclusive_ticks_; 175 return inclusive_ticks_;
176 } 176 }
177 177 void inc_inclusive_ticks() {
178 inclusive_ticks_++;
179 }
178 intptr_t exclusive_ticks() const { 180 intptr_t exclusive_ticks() const {
179 return exclusive_ticks_; 181 return exclusive_ticks_;
180 } 182 }
181 183
182 void Tick(bool exclusive, intptr_t serial) { 184 void Tick(bool exclusive, intptr_t serial) {
183 // Assert that exclusive ticks are never passed a valid serial number. 185 // Assert that exclusive ticks are never passed a valid serial number.
184 ASSERT((exclusive && (serial == -1)) || (!exclusive && (serial != -1))); 186 ASSERT((exclusive && (serial == -1)) || (!exclusive && (serial != -1)));
185 if (!exclusive && (inclusive_tick_serial_ == serial)) { 187 if (!exclusive && (inclusive_tick_serial_ == serial)) {
186 // We've already given this object an inclusive tick for this sample. 188 // We've already given this object an inclusive tick for this sample.
187 return; 189 return;
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 } 431 }
430 int64_t compile_timestamp() const { return compile_timestamp_; } 432 int64_t compile_timestamp() const { return compile_timestamp_; }
431 void set_compile_timestamp(int64_t timestamp) { 433 void set_compile_timestamp(int64_t timestamp) {
432 compile_timestamp_ = timestamp; 434 compile_timestamp_ = timestamp;
433 } 435 }
434 436
435 intptr_t inclusive_ticks() const { return inclusive_ticks_; } 437 intptr_t inclusive_ticks() const { return inclusive_ticks_; }
436 void set_inclusive_ticks(intptr_t inclusive_ticks) { 438 void set_inclusive_ticks(intptr_t inclusive_ticks) {
437 inclusive_ticks_ = inclusive_ticks; 439 inclusive_ticks_ = inclusive_ticks;
438 } 440 }
441 void inc_inclusive_ticks() {
442 inclusive_ticks_++;
443 }
439 444
440 intptr_t exclusive_ticks() const { return exclusive_ticks_; } 445 intptr_t exclusive_ticks() const { return exclusive_ticks_; }
441 void set_exclusive_ticks(intptr_t exclusive_ticks) { 446 void set_exclusive_ticks(intptr_t exclusive_ticks) {
442 exclusive_ticks_ = exclusive_ticks; 447 exclusive_ticks_ = exclusive_ticks;
443 } 448 }
444 449
445 const char* name() const { return name_; } 450 const char* name() const { return name_; }
446 void SetName(const char* name) { 451 void SetName(const char* name) {
447 if (name == NULL) { 452 if (name == NULL) {
448 name_ = NULL; 453 name_ = NULL;
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 ProfileFunctionTrieBuilder(Isolate* isolate, 1410 ProfileFunctionTrieBuilder(Isolate* isolate,
1406 CodeRegionTable* live_code_table, 1411 CodeRegionTable* live_code_table,
1407 CodeRegionTable* dead_code_table, 1412 CodeRegionTable* dead_code_table,
1408 CodeRegionTable* tag_code_table, 1413 CodeRegionTable* tag_code_table,
1409 ProfileFunctionTable* function_table) 1414 ProfileFunctionTable* function_table)
1410 : SampleVisitor(isolate), 1415 : SampleVisitor(isolate),
1411 live_code_table_(live_code_table), 1416 live_code_table_(live_code_table),
1412 dead_code_table_(dead_code_table), 1417 dead_code_table_(dead_code_table),
1413 tag_code_table_(tag_code_table), 1418 tag_code_table_(tag_code_table),
1414 function_table_(function_table), 1419 function_table_(function_table),
1415 inclusive_(false), 1420 inclusive_tree_(false),
1416 trace_(false), 1421 trace_(false),
1417 trace_code_filter_(NULL) { 1422 trace_code_filter_(NULL) {
1418 ASSERT(live_code_table_ != NULL); 1423 ASSERT(live_code_table_ != NULL);
1419 ASSERT(dead_code_table_ != NULL); 1424 ASSERT(dead_code_table_ != NULL);
1420 ASSERT(tag_code_table_ != NULL); 1425 ASSERT(tag_code_table_ != NULL);
1421 ASSERT(function_table_ != NULL); 1426 ASSERT(function_table_ != NULL);
1422 set_tag_order(ProfilerService::kUserVM); 1427 set_tag_order(ProfilerService::kUserVM);
1423 1428
1424 // Verify that the truncated tag exists. 1429 // Verify that the truncated tag exists.
1425 ASSERT(tag_code_table_->FindIndex(VMTag::kTruncatedTagId) >= 0); 1430 ASSERT(tag_code_table_->FindIndex(VMTag::kTruncatedTagId) >= 0);
1426 1431
1427 // Verify that the root tag exists. 1432 // Verify that the root tag exists.
1428 intptr_t root_index = tag_code_table_->FindIndex(VMTag::kRootTagId); 1433 intptr_t root_index = tag_code_table_->FindIndex(VMTag::kRootTagId);
1429 ASSERT(root_index >= 0); 1434 ASSERT(root_index >= 0);
1430 1435
1431 // Setup root. 1436 // Setup root.
1432 CodeRegion* region = tag_code_table_->At(root_index); 1437 CodeRegion* region = tag_code_table_->At(root_index);
1433 ASSERT(region != NULL); 1438 ASSERT(region != NULL);
1434 ProfileFunction* function = region->function(); 1439 ProfileFunction* function = region->function();
1435 ASSERT(function != NULL); 1440 ASSERT(function != NULL);
1436 1441
1437 exclusive_root_ = new ProfileFunctionTrieNode(function->index()); 1442 exclusive_root_ = new ProfileFunctionTrieNode(function->index());
1438 inclusive_root_ = new ProfileFunctionTrieNode(function->index()); 1443 inclusive_root_ = new ProfileFunctionTrieNode(function->index());
1439 } 1444 }
1440 1445
1441 void VisitSample(Sample* sample) { 1446 void VisitSample(Sample* sample) {
1442 inclusive_ = false; 1447 inclusive_tree_ = false;
1443 ProcessSampleExclusive(sample); 1448 ProcessSampleExclusive(sample);
1444 inclusive_ = true; 1449 inclusive_tree_ = true;
1445 ProcessSampleInclusive(sample); 1450 ProcessSampleInclusive(sample);
1446 } 1451 }
1447 1452
1448 ProfileFunctionTrieNode* exclusive_root() const { 1453 ProfileFunctionTrieNode* exclusive_root() const {
1449 return exclusive_root_; 1454 return exclusive_root_;
1450 } 1455 }
1451 1456
1452 ProfileFunctionTrieNode* inclusive_root() const { 1457 ProfileFunctionTrieNode* inclusive_root() const {
1453 return inclusive_root_; 1458 return inclusive_root_;
1454 } 1459 }
1455 1460
1456 ProfilerService::TagOrder tag_order() const { 1461 ProfilerService::TagOrder tag_order() const {
1457 return tag_order_; 1462 return tag_order_;
1458 } 1463 }
1459 1464
1465 bool vm_tags_emitted() const {
1466 return (tag_order_ == ProfilerService::kUserVM) ||
1467 (tag_order_ == ProfilerService::kVMUser) ||
1468 (tag_order_ == ProfilerService::kVM);
1469 }
1470
1460 void set_tag_order(ProfilerService::TagOrder tag_order) { 1471 void set_tag_order(ProfilerService::TagOrder tag_order) {
1461 tag_order_ = tag_order; 1472 tag_order_ = tag_order;
1462 } 1473 }
1463 1474
1464 private: 1475 private:
1465 void ProcessSampleInclusive(Sample* sample) { 1476 void ProcessSampleInclusive(Sample* sample) {
1466 // Give the root a tick. 1477 // Give the root a tick.
1467 inclusive_root_->Tick(); 1478 inclusive_root_->Tick();
1468 ProfileFunctionTrieNode* current = inclusive_root_; 1479 ProfileFunctionTrieNode* current = inclusive_root_;
1469 current = AppendTags(sample, current); 1480 current = AppendTags(sample, current);
1470 if (sample->truncated_trace()) { 1481 if (sample->truncated_trace()) {
1482 InclusiveTickTruncatedTag();
1471 current = AppendTruncatedTag(current); 1483 current = AppendTruncatedTag(current);
1472 } 1484 }
1473 // Walk the sampled PCs. 1485 // Walk the sampled PCs.
1474 for (intptr_t i = FLAG_profile_depth - 1; i >= 0; i--) { 1486 for (intptr_t i = FLAG_profile_depth - 1; i >= 0; i--) {
1475 if (sample->At(i) == 0) { 1487 if (sample->At(i) == 0) {
1476 continue; 1488 continue;
1477 } 1489 }
1478 // If we aren't sampled out of an exit frame and this is the top 1490 current = ProcessPC(sample->At(i),
1479 // frame. 1491 sample->timestamp(),
1480 bool exclusive_tick = (i == 0) && !sample->exit_frame_sample(); 1492 current,
1481 current = ProcessPC(sample->At(i), sample->timestamp(), current, 1493 visited(),
1482 visited(), exclusive_tick, 1494 (i == 0),
1495 sample->exit_frame_sample() && (i == 0),
1483 sample->missing_frame_inserted()); 1496 sample->missing_frame_inserted());
1484 } 1497 }
1485 } 1498 }
1486 1499
1487 void ProcessSampleExclusive(Sample* sample) { 1500 void ProcessSampleExclusive(Sample* sample) {
1488 // Give the root a tick. 1501 // Give the root a tick.
1489 exclusive_root_->Tick(); 1502 exclusive_root_->Tick();
1490 ProfileFunctionTrieNode* current = exclusive_root_; 1503 ProfileFunctionTrieNode* current = exclusive_root_;
1491 current = AppendTags(sample, current); 1504 current = AppendTags(sample, current);
1492 // Walk the sampled PCs. 1505 // Walk the sampled PCs.
1493 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 1506 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
1494 if (sample->At(i) == 0) { 1507 if (sample->At(i) == 0) {
1495 break; 1508 break;
1496 } 1509 }
1497 // If we aren't sampled out of an exit frame and this is the top 1510 current = ProcessPC(sample->At(i),
1498 // frame. 1511 sample->timestamp(),
1499 bool exclusive_tick = (i == 0) && !sample->exit_frame_sample(); 1512 current,
1500 current = ProcessPC(sample->At(i), sample->timestamp(), current, 1513 visited(),
1501 visited(), exclusive_tick, 1514 (i == 0),
1515 sample->exit_frame_sample() && (i == 0),
1502 sample->missing_frame_inserted()); 1516 sample->missing_frame_inserted());
1503 } 1517 }
1504 if (sample->truncated_trace()) { 1518 if (sample->truncated_trace()) {
1505 current = AppendTruncatedTag(current); 1519 current = AppendTruncatedTag(current);
1506 } 1520 }
1507 } 1521 }
1508 1522
1509 ProfileFunctionTrieNode* AppendUserTag(Sample* sample, 1523 ProfileFunctionTrieNode* AppendUserTag(Sample* sample,
1510 ProfileFunctionTrieNode* current) { 1524 ProfileFunctionTrieNode* current) {
1511 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); 1525 intptr_t user_tag_index = FindTagIndex(sample->user_tag());
1512 if (user_tag_index >= 0) { 1526 if (user_tag_index >= 0) {
1513 current = current->GetChild(user_tag_index); 1527 current = current->GetChild(user_tag_index);
1514 // Give the tag a tick. 1528 // Give the tag a tick.
1515 current->Tick(); 1529 current->Tick();
1516 } 1530 }
1517 return current; 1531 return current;
1518 } 1532 }
1519 1533
1520 1534
1521 ProfileFunctionTrieNode* AppendTruncatedTag( 1535 ProfileFunctionTrieNode* AppendTruncatedTag(
1522 ProfileFunctionTrieNode* current) { 1536 ProfileFunctionTrieNode* current) {
1523 intptr_t truncated_tag_index = FindTagIndex(VMTag::kTruncatedTagId); 1537 intptr_t truncated_tag_index = FindTagIndex(VMTag::kTruncatedTagId);
1524 ASSERT(truncated_tag_index >= 0); 1538 ASSERT(truncated_tag_index >= 0);
1525 current = current->GetChild(truncated_tag_index); 1539 current = current->GetChild(truncated_tag_index);
1526 current->Tick(); 1540 current->Tick();
1527 return current; 1541 return current;
1528 } 1542 }
1529 1543
1544 void InclusiveTickTruncatedTag() {
1545 intptr_t index = tag_code_table_->FindIndex(VMTag::kTruncatedTagId);
1546 CodeRegion* region = tag_code_table_->At(index);
1547 ProfileFunction* function = region->function();
1548 function->inc_inclusive_ticks();
1549 }
1530 1550
1531 ProfileFunctionTrieNode* AppendVMTag(Sample* sample, 1551 ProfileFunctionTrieNode* AppendVMTag(Sample* sample,
1532 ProfileFunctionTrieNode* current) { 1552 ProfileFunctionTrieNode* current) {
1533 if (VMTag::IsNativeEntryTag(sample->vm_tag())) { 1553 if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
1534 // Insert a dummy kNativeTagId node. 1554 // Insert a dummy kNativeTagId node.
1535 intptr_t tag_index = FindTagIndex(VMTag::kNativeTagId); 1555 intptr_t tag_index = FindTagIndex(VMTag::kNativeTagId);
1536 current = current->GetChild(tag_index); 1556 current = current->GetChild(tag_index);
1537 // Give the tag a tick. 1557 // Give the tag a tick.
1538 current->Tick(); 1558 current->Tick();
1539 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { 1559 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1617 return function->index(); 1637 return function->index();
1618 } 1638 }
1619 1639
1620 void Dump(ProfileFunctionTrieNode* current) { 1640 void Dump(ProfileFunctionTrieNode* current) {
1621 int current_index = current->profile_function_table_index(); 1641 int current_index = current->profile_function_table_index();
1622 ProfileFunction* function = function_table_->At(current_index); 1642 ProfileFunction* function = function_table_->At(current_index);
1623 function->Dump(); 1643 function->Dump();
1624 OS::Print("\n"); 1644 OS::Print("\n");
1625 } 1645 }
1626 1646
1627 ProfileFunctionTrieNode* ProcessPC(uword pc, int64_t timestamp, 1647 ProfileFunctionTrieNode* ProcessPC(uword pc,
1648 int64_t timestamp,
1628 ProfileFunctionTrieNode* current, 1649 ProfileFunctionTrieNode* current,
1629 intptr_t inclusive_serial, 1650 intptr_t inclusive_serial,
1630 bool exclusive, 1651 bool top_frame,
1652 bool exit_frame,
1631 bool missing_frame_inserted) { 1653 bool missing_frame_inserted) {
1632 CodeRegion* region = FindCodeObject(pc, timestamp); 1654 CodeRegion* region = FindCodeObject(pc, timestamp);
1633 if (region == NULL) { 1655 if (region == NULL) {
1634 return current; 1656 return current;
1635 } 1657 }
1636 const char* region_name = region->name(); 1658 const char* region_name = region->name();
1637 if (region_name == NULL) { 1659 if (region_name == NULL) {
1638 region_name = ""; 1660 region_name = "";
1639 } 1661 }
1640 intptr_t code_index = region->code_table_index(); 1662 intptr_t code_index = region->code_table_index();
1641 const Code& code = Code::ZoneHandle(region->code()); 1663 const Code& code = Code::ZoneHandle(region->code());
1642 GrowableArray<Function*> inlined_functions; 1664 GrowableArray<Function*> inlined_functions;
1643 if (!code.IsNull()) { 1665 if (!code.IsNull()) {
1644 intptr_t offset = pc - code.EntryPoint(); 1666 intptr_t offset = pc - code.EntryPoint();
1645 code.GetInlinedFunctionsAt(offset, &inlined_functions); 1667 code.GetInlinedFunctionsAt(offset, &inlined_functions);
1646 } 1668 }
1647 if (code.IsNull() || (inlined_functions.length() == 0)) { 1669 if (code.IsNull() || (inlined_functions.length() == 0)) {
1648 // No inlined functions. 1670 // No inlined functions.
1649 ProfileFunction* function = region->function(); 1671 ProfileFunction* function = region->function();
1650 ASSERT(function != NULL); 1672 ASSERT(function != NULL);
1651 if (trace_) { 1673 if (trace_) {
1652 OS::Print("[%" Px "] X - %s (%s)\n", 1674 OS::Print("[%" Px "] X - %s (%s)\n",
1653 pc, function->name(), region_name); 1675 pc, function->name(), region_name);
1654 } 1676 }
1655 if (!inclusive_) { 1677 current = ProcessFunction(function,
1656 function->Tick(exclusive, exclusive ? -1 : inclusive_serial); 1678 current,
1657 } 1679 inclusive_serial,
1658 current = current->GetChild(function->index()); 1680 top_frame,
1659 current->AddCodeObjectIndex(code_index); 1681 exit_frame,
1660 current->Tick(); 1682 code_index);
1661 if ((trace_code_filter_ != NULL) && 1683 if ((trace_code_filter_ != NULL) &&
1662 (strstr(region_name, trace_code_filter_) != NULL)) { 1684 (strstr(region_name, trace_code_filter_) != NULL)) {
1663 trace_ = true; 1685 trace_ = true;
1664 OS::Print("Tracing from: %" Px " [%s] ", pc, 1686 OS::Print("Tracing from: %" Px " [%s] ", pc,
1665 missing_frame_inserted ? "INSERTED" : ""); 1687 missing_frame_inserted ? "INSERTED" : "");
1666 Dump(current); 1688 Dump(current);
1667 } 1689 }
1668 return current; 1690 return current;
1669 } 1691 }
1670 1692
1671 if (inclusive_) { 1693 if (inclusive_tree_) {
1672 for (intptr_t i = inlined_functions.length() - 1; i >= 0; i--) { 1694 for (intptr_t i = inlined_functions.length() - 1; i >= 0; i--) {
1673 Function* inlined_function = inlined_functions[i]; 1695 Function* inlined_function = inlined_functions[i];
1674 ASSERT(inlined_function != NULL); 1696 ASSERT(inlined_function != NULL);
1675 ASSERT(!inlined_function->IsNull()); 1697 ASSERT(!inlined_function->IsNull());
1676 current = ProcessInlinedFunction( 1698 current = ProcessInlinedFunction(inlined_function,
1677 inlined_function, current, inclusive_serial, exclusive, code_index); 1699 current,
1678 exclusive = false; 1700 inclusive_serial,
1701 top_frame,
1702 exit_frame,
1703 code_index);
1704 top_frame = false;
1679 } 1705 }
1680 } else { 1706 } else {
1681 for (intptr_t i = 0; i < inlined_functions.length(); i++) { 1707 for (intptr_t i = 0; i < inlined_functions.length(); i++) {
1682 Function* inlined_function = inlined_functions[i]; 1708 Function* inlined_function = inlined_functions[i];
1683 ASSERT(inlined_function != NULL); 1709 ASSERT(inlined_function != NULL);
1684 ASSERT(!inlined_function->IsNull()); 1710 ASSERT(!inlined_function->IsNull());
1685 const char* inline_name = inlined_function->ToQualifiedCString(); 1711 const char* inline_name = inlined_function->ToQualifiedCString();
1686 if (trace_) { 1712 if (trace_) {
1687 OS::Print("[%" Px "] %" Pd " - %s (%s)\n", 1713 OS::Print("[%" Px "] %" Pd " - %s (%s)\n",
1688 pc, i, inline_name, region_name); 1714 pc, i, inline_name, region_name);
1689 } 1715 }
1690 current = ProcessInlinedFunction( 1716 current = ProcessInlinedFunction(inlined_function,
1691 inlined_function, current, inclusive_serial, exclusive, code_index); 1717 current,
1692 exclusive = false; 1718 inclusive_serial,
1719 top_frame,
1720 exit_frame,
1721 code_index);
1722 top_frame = false;
1693 if ((trace_code_filter_ != NULL) && 1723 if ((trace_code_filter_ != NULL) &&
1694 (strstr(region_name, trace_code_filter_) != NULL)) { 1724 (strstr(region_name, trace_code_filter_) != NULL)) {
1695 trace_ = true; 1725 trace_ = true;
1696 OS::Print("Tracing from: %" Px " [%s] ", 1726 OS::Print("Tracing from: %" Px " [%s] ",
1697 pc, missing_frame_inserted ? "INSERTED" : ""); 1727 pc, missing_frame_inserted ? "INSERTED" : "");
1698 Dump(current); 1728 Dump(current);
1699 } 1729 }
1700 } 1730 }
1701 } 1731 }
1702 1732
1703 return current; 1733 return current;
1704 } 1734 }
1705 1735
1706 ProfileFunctionTrieNode* ProcessInlinedFunction( 1736 ProfileFunctionTrieNode* ProcessInlinedFunction(
1707 Function* inlined_function, 1737 Function* inlined_function,
1708 ProfileFunctionTrieNode* current, 1738 ProfileFunctionTrieNode* current,
1709 intptr_t inclusive_serial, 1739 intptr_t inclusive_serial,
1710 bool exclusive, 1740 bool top_frame,
1741 bool exit_frame,
1711 intptr_t code_index) { 1742 intptr_t code_index) {
1712 ProfileFunction* function = 1743 ProfileFunction* function =
1713 function_table_->LookupOrAdd(*inlined_function); 1744 function_table_->LookupOrAdd(*inlined_function);
1714 ASSERT(function != NULL); 1745 ASSERT(function != NULL);
1746 return ProcessFunction(function,
1747 current,
1748 inclusive_serial,
1749 top_frame,
1750 exit_frame,
1751 code_index);
1752 }
1753
1754 ProfileFunctionTrieNode* ProcessFunction(ProfileFunction* function,
1755 ProfileFunctionTrieNode* current,
1756 intptr_t inclusive_serial,
1757 bool top_frame,
1758 bool exit_frame,
1759 intptr_t code_index) {
1760 const bool exclusive = top_frame && !exit_frame;
1761 if (!inclusive_tree_) {
1762 // We process functions for the inclusive and exclusive trees.
1763 // Only tick the function for the exclusive tree.
1764 function->Tick(exclusive, exclusive ? -1 : inclusive_serial);
1765 }
1715 function->AddCodeObjectIndex(code_index); 1766 function->AddCodeObjectIndex(code_index);
1716 function->Tick(exclusive, exclusive ? -1 : inclusive_serial); 1767
1717 current = current->GetChild(function->index()); 1768 current = current->GetChild(function->index());
1718 current->AddCodeObjectIndex(code_index); 1769 current->AddCodeObjectIndex(code_index);
1719 current->Tick(); 1770 if (top_frame) {
1771 if (!exit_frame || vm_tags_emitted()) {
1772 // Only tick if this isn't an exit frame or VM tags are emitted.
1773 current->Tick();
1774 }
1775 } else {
1776 current->Tick();
1777 }
1720 return current; 1778 return current;
1721 } 1779 }
1722 1780
1723 CodeRegion* FindCodeObject(uword pc, int64_t timestamp) const { 1781 CodeRegion* FindCodeObject(uword pc, int64_t timestamp) const {
1724 intptr_t index = live_code_table_->FindIndex(pc); 1782 intptr_t index = live_code_table_->FindIndex(pc);
1725 if (index < 0) { 1783 if (index < 0) {
1726 return NULL; 1784 return NULL;
1727 } 1785 }
1728 CodeRegion* region = live_code_table_->At(index); 1786 CodeRegion* region = live_code_table_->At(index);
1729 ASSERT(region->contains(pc)); 1787 ASSERT(region->contains(pc));
(...skipping 12 matching lines...) Expand all
1742 return region; 1800 return region;
1743 } 1801 }
1744 1802
1745 ProfilerService::TagOrder tag_order_; 1803 ProfilerService::TagOrder tag_order_;
1746 ProfileFunctionTrieNode* exclusive_root_; 1804 ProfileFunctionTrieNode* exclusive_root_;
1747 ProfileFunctionTrieNode* inclusive_root_; 1805 ProfileFunctionTrieNode* inclusive_root_;
1748 CodeRegionTable* live_code_table_; 1806 CodeRegionTable* live_code_table_;
1749 CodeRegionTable* dead_code_table_; 1807 CodeRegionTable* dead_code_table_;
1750 CodeRegionTable* tag_code_table_; 1808 CodeRegionTable* tag_code_table_;
1751 ProfileFunctionTable* function_table_; 1809 ProfileFunctionTable* function_table_;
1752 bool inclusive_; 1810 bool inclusive_tree_;
1753 bool trace_; 1811 bool trace_;
1754 const char* trace_code_filter_; 1812 const char* trace_code_filter_;
1755 }; 1813 };
1756 1814
1757 1815
1758 class CodeRegionTrieNode : public ZoneAllocated { 1816 class CodeRegionTrieNode : public ZoneAllocated {
1759 public: 1817 public:
1760 explicit CodeRegionTrieNode(intptr_t code_region_index) 1818 explicit CodeRegionTrieNode(intptr_t code_region_index)
1761 : code_region_index_(code_region_index), 1819 : code_region_index_(code_region_index),
1762 count_(0), 1820 count_(0),
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1885 } 1943 }
1886 1944
1887 CodeRegionTrieNode* exclusive_root() const { 1945 CodeRegionTrieNode* exclusive_root() const {
1888 return exclusive_root_; 1946 return exclusive_root_;
1889 } 1947 }
1890 1948
1891 ProfilerService::TagOrder tag_order() const { 1949 ProfilerService::TagOrder tag_order() const {
1892 return tag_order_; 1950 return tag_order_;
1893 } 1951 }
1894 1952
1953 bool vm_tags_emitted() const {
1954 return (tag_order_ == ProfilerService::kUserVM) ||
1955 (tag_order_ == ProfilerService::kVMUser) ||
1956 (tag_order_ == ProfilerService::kVM);
1957 }
1958
1895 void set_tag_order(ProfilerService::TagOrder tag_order) { 1959 void set_tag_order(ProfilerService::TagOrder tag_order) {
1896 tag_order_ = tag_order; 1960 tag_order_ = tag_order;
1897 } 1961 }
1898 1962
1899 private: 1963 private:
1900 void ProcessSampleInclusive(Sample* sample) { 1964 void ProcessSampleInclusive(Sample* sample) {
1901 // Give the root a tick. 1965 // Give the root a tick.
1902 inclusive_root_->Tick(); 1966 inclusive_root_->Tick();
1903 CodeRegionTrieNode* current = inclusive_root_; 1967 CodeRegionTrieNode* current = inclusive_root_;
1904 current = AppendTags(sample, current); 1968 current = AppendTags(sample, current);
(...skipping 22 matching lines...) Expand all
1927 // Walk the sampled PCs. 1991 // Walk the sampled PCs.
1928 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 1992 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
1929 if (sample->At(i) == 0) { 1993 if (sample->At(i) == 0) {
1930 break; 1994 break;
1931 } 1995 }
1932 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp()); 1996 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp());
1933 if (index < 0) { 1997 if (index < 0) {
1934 continue; 1998 continue;
1935 } 1999 }
1936 current = current->GetChild(index); 2000 current = current->GetChild(index);
1937 current->Tick(); 2001 if (i == 0) {
2002 // Executing PC.
2003 if (!sample->exit_frame_sample() || vm_tags_emitted()) {
2004 // Only tick if this isn't an exit frame or VM tags are emitted.
2005 current->Tick();
2006 }
2007 } else {
2008 // Caller PCs.
2009 current->Tick();
2010 }
1938 } 2011 }
1939 if (sample->truncated_trace()) { 2012 if (sample->truncated_trace()) {
1940 current = AppendTruncatedTag(current); 2013 current = AppendTruncatedTag(current);
1941 } 2014 }
1942 } 2015 }
1943 2016
1944 CodeRegionTrieNode* AppendUserTag(Sample* sample, 2017 CodeRegionTrieNode* AppendUserTag(Sample* sample,
1945 CodeRegionTrieNode* current) { 2018 CodeRegionTrieNode* current) {
1946 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); 2019 intptr_t user_tag_index = FindTagIndex(sample->user_tag());
1947 if (user_tag_index >= 0) { 2020 if (user_tag_index >= 0) {
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
2129 { 2202 {
2130 ScopeTimer sw("CodeRegionTableBuilder", FLAG_trace_profiler); 2203 ScopeTimer sw("CodeRegionTableBuilder", FLAG_trace_profiler);
2131 sample_buffer->VisitSamples(&builder); 2204 sample_buffer->VisitSamples(&builder);
2132 } 2205 }
2133 intptr_t samples = builder.visited(); 2206 intptr_t samples = builder.visited();
2134 intptr_t frames = builder.frames(); 2207 intptr_t frames = builder.frames();
2135 if (FLAG_trace_profiler) { 2208 if (FLAG_trace_profiler) {
2136 intptr_t total_live_code_objects = live_code_table.Length(); 2209 intptr_t total_live_code_objects = live_code_table.Length();
2137 intptr_t total_dead_code_objects = dead_code_table.Length(); 2210 intptr_t total_dead_code_objects = dead_code_table.Length();
2138 intptr_t total_tag_code_objects = tag_code_table.Length(); 2211 intptr_t total_tag_code_objects = tag_code_table.Length();
2139 OS::Print("Processed %" Pd " frames\n", frames); 2212 OS::Print(
2213 "Processed %" Pd " samples with %" Pd " frames\n", samples, frames);
2140 OS::Print("CodeTables: live=%" Pd " dead=%" Pd " tag=%" Pd "\n", 2214 OS::Print("CodeTables: live=%" Pd " dead=%" Pd " tag=%" Pd "\n",
2141 total_live_code_objects, 2215 total_live_code_objects,
2142 total_dead_code_objects, 2216 total_dead_code_objects,
2143 total_tag_code_objects); 2217 total_tag_code_objects);
2144 } 2218 }
2145 2219
2146 if (FLAG_trace_profiler) { 2220 if (FLAG_trace_profiler) {
2147 ScopeTimer sw("CodeRegionTableVerify", FLAG_trace_profiler); 2221 ScopeTimer sw("CodeRegionTableVerify", FLAG_trace_profiler);
2148 live_code_table.Verify(); 2222 live_code_table.Verify();
2149 dead_code_table.Verify(); 2223 dead_code_table.Verify();
(...skipping 17 matching lines...) Expand all
2167 &dead_code_table, 2241 &dead_code_table,
2168 &tag_code_table); 2242 &tag_code_table);
2169 code_trie_builder.set_tag_order(tag_order); 2243 code_trie_builder.set_tag_order(tag_order);
2170 { 2244 {
2171 // Build CodeRegion trie. 2245 // Build CodeRegion trie.
2172 ScopeTimer sw("CodeRegionTrieBuilder", FLAG_trace_profiler); 2246 ScopeTimer sw("CodeRegionTrieBuilder", FLAG_trace_profiler);
2173 sample_buffer->VisitSamples(&code_trie_builder); 2247 sample_buffer->VisitSamples(&code_trie_builder);
2174 code_trie_builder.exclusive_root()->SortByCount(); 2248 code_trie_builder.exclusive_root()->SortByCount();
2175 code_trie_builder.inclusive_root()->SortByCount(); 2249 code_trie_builder.inclusive_root()->SortByCount();
2176 } 2250 }
2251 if (FLAG_trace_profiler) {
2252 OS::Print("Code Trie Root Count: E: %" Pd " I: %" Pd "\n",
2253 code_trie_builder.exclusive_root()->count(),
2254 code_trie_builder.inclusive_root()->count());
2255 }
2177 ProfileFunctionTrieBuilder function_trie_builder(isolate, 2256 ProfileFunctionTrieBuilder function_trie_builder(isolate,
2178 &live_code_table, 2257 &live_code_table,
2179 &dead_code_table, 2258 &dead_code_table,
2180 &tag_code_table, 2259 &tag_code_table,
2181 &function_table); 2260 &function_table);
2182 function_trie_builder.set_tag_order(tag_order); 2261 function_trie_builder.set_tag_order(tag_order);
2183 { 2262 {
2184 // Build ProfileFunction trie. 2263 // Build ProfileFunction trie.
2185 ScopeTimer sw("ProfileFunctionTrieBuilder", 2264 ScopeTimer sw("ProfileFunctionTrieBuilder",
2186 FLAG_trace_profiler); 2265 FLAG_trace_profiler);
2187 sample_buffer->VisitSamples(&function_trie_builder); 2266 sample_buffer->VisitSamples(&function_trie_builder);
2188 function_trie_builder.exclusive_root()->SortByCount(); 2267 function_trie_builder.exclusive_root()->SortByCount();
2189 function_trie_builder.inclusive_root()->SortByCount(); 2268 function_trie_builder.inclusive_root()->SortByCount();
2190 } 2269 }
2270 if (FLAG_trace_profiler) {
2271 OS::Print("Function Trie Root Count: E: %" Pd " I: %" Pd "\n",
2272 function_trie_builder.exclusive_root()->count(),
2273 function_trie_builder.inclusive_root()->count());
2274 }
2191 { 2275 {
2192 ScopeTimer sw("CpuProfileJSONStream", FLAG_trace_profiler); 2276 ScopeTimer sw("CpuProfileJSONStream", FLAG_trace_profiler);
2193 // Serialize to JSON. 2277 // Serialize to JSON.
2194 JSONObject obj(stream); 2278 JSONObject obj(stream);
2195 obj.AddProperty("type", "_CpuProfile"); 2279 obj.AddProperty("type", "_CpuProfile");
2196 obj.AddProperty("sampleCount", samples); 2280 obj.AddProperty("sampleCount", samples);
2197 obj.AddProperty("samplePeriod", 2281 obj.AddProperty("samplePeriod",
2198 static_cast<intptr_t>(FLAG_profile_period)); 2282 static_cast<intptr_t>(FLAG_profile_period));
2199 obj.AddProperty("stackDepth", 2283 obj.AddProperty("stackDepth",
2200 static_cast<intptr_t>(FLAG_profile_depth)); 2284 static_cast<intptr_t>(FLAG_profile_depth));
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2277 ASSERT(sample_buffer != NULL); 2361 ASSERT(sample_buffer != NULL);
2278 2362
2279 ClearProfileVisitor clear_profile(isolate); 2363 ClearProfileVisitor clear_profile(isolate);
2280 sample_buffer->VisitSamples(&clear_profile); 2364 sample_buffer->VisitSamples(&clear_profile);
2281 2365
2282 // Enable profile interrupts. 2366 // Enable profile interrupts.
2283 Profiler::BeginExecution(isolate); 2367 Profiler::BeginExecution(isolate);
2284 } 2368 }
2285 2369
2286 } // namespace dart 2370 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/elements/cpu_profile.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698