Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/profiler_service.h" | 5 #include "vm/profiler_service.h" |
| 6 | 6 |
| 7 #include "vm/growable_array.h" | 7 #include "vm/growable_array.h" |
| 8 #include "vm/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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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); | |
|
Ivan Posva
2015/03/16 22:17:37
I am wondering whether some of this information co
| |
| 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 Loading... | |
| 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 exclusive_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 exclusive_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 exclusive_frame, | |
| 1702 exit_frame, | |
| 1703 code_index); | |
| 1704 exclusive_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 exclusive_frame, | |
| 1720 exit_frame, | |
| 1721 code_index); | |
| 1722 exclusive_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 exclusive_frame, |
|
Ivan Posva
2015/03/16 22:17:37
exclusive_frame really means the 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 exclusive_frame, | |
| 1750 exit_frame, | |
| 1751 code_index); | |
| 1752 } | |
| 1753 | |
| 1754 ProfileFunctionTrieNode* ProcessFunction(ProfileFunction* function, | |
| 1755 ProfileFunctionTrieNode* current, | |
| 1756 intptr_t inclusive_serial, | |
| 1757 bool exclusive_frame, | |
| 1758 bool exit_frame, | |
| 1759 intptr_t code_index) { | |
| 1760 const bool exclusive = exclusive_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 (exclusive_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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2126 &dead_code_table, | 2199 &dead_code_table, |
| 2127 &tag_code_table, | 2200 &tag_code_table, |
| 2128 deoptimized_code); | 2201 deoptimized_code); |
| 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) { |
| 2209 OS::Print( | |
| 2210 "Processed %" Pd " samples with %" Pd " frames\n", samples, frames); | |
| 2211 } | |
|
Ivan Posva
2015/03/16 22:17:37
if (x) {
}
if (x) {
}
???
| |
| 2212 if (FLAG_trace_profiler) { | |
| 2136 intptr_t total_live_code_objects = live_code_table.Length(); | 2213 intptr_t total_live_code_objects = live_code_table.Length(); |
| 2137 intptr_t total_dead_code_objects = dead_code_table.Length(); | 2214 intptr_t total_dead_code_objects = dead_code_table.Length(); |
| 2138 intptr_t total_tag_code_objects = tag_code_table.Length(); | 2215 intptr_t total_tag_code_objects = tag_code_table.Length(); |
| 2139 OS::Print("Processed %" Pd " frames\n", frames); | 2216 |
| 2140 OS::Print("CodeTables: live=%" Pd " dead=%" Pd " tag=%" Pd "\n", | 2217 OS::Print("CodeTables: live=%" Pd " dead=%" Pd " tag=%" Pd "\n", |
| 2141 total_live_code_objects, | 2218 total_live_code_objects, |
| 2142 total_dead_code_objects, | 2219 total_dead_code_objects, |
| 2143 total_tag_code_objects); | 2220 total_tag_code_objects); |
| 2144 } | 2221 } |
| 2145 | 2222 |
| 2146 if (FLAG_trace_profiler) { | 2223 if (FLAG_trace_profiler) { |
| 2147 ScopeTimer sw("CodeRegionTableVerify", FLAG_trace_profiler); | 2224 ScopeTimer sw("CodeRegionTableVerify", FLAG_trace_profiler); |
| 2148 live_code_table.Verify(); | 2225 live_code_table.Verify(); |
| 2149 dead_code_table.Verify(); | 2226 dead_code_table.Verify(); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 2167 &dead_code_table, | 2244 &dead_code_table, |
| 2168 &tag_code_table); | 2245 &tag_code_table); |
| 2169 code_trie_builder.set_tag_order(tag_order); | 2246 code_trie_builder.set_tag_order(tag_order); |
| 2170 { | 2247 { |
| 2171 // Build CodeRegion trie. | 2248 // Build CodeRegion trie. |
| 2172 ScopeTimer sw("CodeRegionTrieBuilder", FLAG_trace_profiler); | 2249 ScopeTimer sw("CodeRegionTrieBuilder", FLAG_trace_profiler); |
| 2173 sample_buffer->VisitSamples(&code_trie_builder); | 2250 sample_buffer->VisitSamples(&code_trie_builder); |
| 2174 code_trie_builder.exclusive_root()->SortByCount(); | 2251 code_trie_builder.exclusive_root()->SortByCount(); |
| 2175 code_trie_builder.inclusive_root()->SortByCount(); | 2252 code_trie_builder.inclusive_root()->SortByCount(); |
| 2176 } | 2253 } |
| 2254 if (FLAG_trace_profiler) { | |
| 2255 OS::Print("Code Trie Root Count: E: %" Pd " I: %" Pd "\n", | |
| 2256 code_trie_builder.exclusive_root()->count(), | |
| 2257 code_trie_builder.inclusive_root()->count()); | |
| 2258 } | |
| 2177 ProfileFunctionTrieBuilder function_trie_builder(isolate, | 2259 ProfileFunctionTrieBuilder function_trie_builder(isolate, |
| 2178 &live_code_table, | 2260 &live_code_table, |
| 2179 &dead_code_table, | 2261 &dead_code_table, |
| 2180 &tag_code_table, | 2262 &tag_code_table, |
| 2181 &function_table); | 2263 &function_table); |
| 2182 function_trie_builder.set_tag_order(tag_order); | 2264 function_trie_builder.set_tag_order(tag_order); |
| 2183 { | 2265 { |
| 2184 // Build ProfileFunction trie. | 2266 // Build ProfileFunction trie. |
| 2185 ScopeTimer sw("ProfileFunctionTrieBuilder", | 2267 ScopeTimer sw("ProfileFunctionTrieBuilder", |
| 2186 FLAG_trace_profiler); | 2268 FLAG_trace_profiler); |
| 2187 sample_buffer->VisitSamples(&function_trie_builder); | 2269 sample_buffer->VisitSamples(&function_trie_builder); |
| 2188 function_trie_builder.exclusive_root()->SortByCount(); | 2270 function_trie_builder.exclusive_root()->SortByCount(); |
| 2189 function_trie_builder.inclusive_root()->SortByCount(); | 2271 function_trie_builder.inclusive_root()->SortByCount(); |
| 2190 } | 2272 } |
| 2273 if (FLAG_trace_profiler) { | |
| 2274 OS::Print("Function Trie Root Count: E: %" Pd " I: %" Pd "\n", | |
| 2275 function_trie_builder.exclusive_root()->count(), | |
| 2276 function_trie_builder.inclusive_root()->count()); | |
| 2277 } | |
| 2191 { | 2278 { |
| 2192 ScopeTimer sw("CpuProfileJSONStream", FLAG_trace_profiler); | 2279 ScopeTimer sw("CpuProfileJSONStream", FLAG_trace_profiler); |
| 2193 // Serialize to JSON. | 2280 // Serialize to JSON. |
| 2194 JSONObject obj(stream); | 2281 JSONObject obj(stream); |
| 2195 obj.AddProperty("type", "_CpuProfile"); | 2282 obj.AddProperty("type", "_CpuProfile"); |
| 2196 obj.AddProperty("sampleCount", samples); | 2283 obj.AddProperty("sampleCount", samples); |
| 2197 obj.AddProperty("samplePeriod", | 2284 obj.AddProperty("samplePeriod", |
| 2198 static_cast<intptr_t>(FLAG_profile_period)); | 2285 static_cast<intptr_t>(FLAG_profile_period)); |
| 2199 obj.AddProperty("stackDepth", | 2286 obj.AddProperty("stackDepth", |
| 2200 static_cast<intptr_t>(FLAG_profile_depth)); | 2287 static_cast<intptr_t>(FLAG_profile_depth)); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2277 ASSERT(sample_buffer != NULL); | 2364 ASSERT(sample_buffer != NULL); |
| 2278 | 2365 |
| 2279 ClearProfileVisitor clear_profile(isolate); | 2366 ClearProfileVisitor clear_profile(isolate); |
| 2280 sample_buffer->VisitSamples(&clear_profile); | 2367 sample_buffer->VisitSamples(&clear_profile); |
| 2281 | 2368 |
| 2282 // Enable profile interrupts. | 2369 // Enable profile interrupts. |
| 2283 Profiler::BeginExecution(isolate); | 2370 Profiler::BeginExecution(isolate); |
| 2284 } | 2371 } |
| 2285 | 2372 |
| 2286 } // namespace dart | 2373 } // namespace dart |
| OLD | NEW |