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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 if (exclusive) { | 189 if (exclusive) { |
190 exclusive_ticks_++; | 190 exclusive_ticks_++; |
191 } else { | 191 } else { |
192 inclusive_ticks_++; | 192 inclusive_ticks_++; |
193 // Mark the last serial we ticked the inclusive count. | 193 // Mark the last serial we ticked the inclusive count. |
194 inclusive_tick_serial_ = serial; | 194 inclusive_tick_serial_ = serial; |
195 } | 195 } |
196 } | 196 } |
197 | 197 |
198 void PrintToJSONObject(JSONObject* func) { | 198 void PrintToJSONObject(JSONObject* func) { |
199 if (kind() == kNativeFunction) { | 199 func->AddProperty("type", "@Function"); |
200 func->AddProperty("type", "@Function"); | 200 func->AddProperty("name", name()); |
201 func->AddProperty("name", name()); | 201 func->AddProperty("kind", KindToCString(kind())); |
202 func->AddProperty("kind", "Native"); | |
203 } else if (kind() == kTagFunction) { | |
204 func->AddProperty("type", "@Function"); | |
205 func->AddProperty("kind", "Tag"); | |
206 func->AddProperty("name", name()); | |
207 } else if (kind() == kUnkownFunction) { | |
208 func->AddProperty("type", "@Function"); | |
209 func->AddProperty("name", name()); | |
210 func->AddProperty("kind", "Collected"); | |
211 } else if (kind() == kStubFunction) { | |
212 func->AddProperty("type", "@Function"); | |
213 func->AddProperty("name", name()); | |
214 func->AddProperty("kind", "Stub"); | |
215 } else { | |
216 UNREACHABLE(); | |
217 } | |
218 } | 202 } |
219 | 203 |
220 void PrintToJSONArray(JSONArray* functions) { | 204 void PrintToJSONArray(JSONArray* functions) { |
221 JSONObject obj(functions); | 205 JSONObject obj(functions); |
222 obj.AddProperty("kind", KindToCString(kind())); | 206 obj.AddProperty("kind", KindToCString(kind())); |
223 obj.AddPropertyF("inclusiveTicks", "%" Pd "", inclusive_ticks()); | 207 obj.AddPropertyF("inclusiveTicks", "%" Pd "", inclusive_ticks()); |
224 obj.AddPropertyF("exclusiveTicks", "%" Pd "", exclusive_ticks()); | 208 obj.AddPropertyF("exclusiveTicks", "%" Pd "", exclusive_ticks()); |
225 if (kind() == kDartFunction) { | 209 if (kind() == kDartFunction) { |
226 ASSERT(!function_.IsNull()); | 210 ASSERT(!function_.IsNull()); |
227 obj.AddProperty("function", function_); | 211 obj.AddProperty("function", function_); |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 // Generate a fake function entry. | 607 // Generate a fake function entry. |
624 JSONObject func(&obj, "function"); | 608 JSONObject func(&obj, "function"); |
625 profile_function_->PrintToJSONObject(&func); | 609 profile_function_->PrintToJSONObject(&func); |
626 } | 610 } |
627 } | 611 } |
628 | 612 |
629 void PrintOverwrittenCode(JSONObject* profile_code_obj) { | 613 void PrintOverwrittenCode(JSONObject* profile_code_obj) { |
630 ASSERT(kind() == kReusedCode); | 614 ASSERT(kind() == kReusedCode); |
631 JSONObject obj(profile_code_obj, "code"); | 615 JSONObject obj(profile_code_obj, "code"); |
632 obj.AddProperty("type", "@Code"); | 616 obj.AddProperty("type", "@Code"); |
633 obj.AddProperty("kind", "Reused"); | 617 obj.AddProperty("kind", "Collected"); |
634 obj.AddProperty("name", name()); | 618 obj.AddProperty("name", name()); |
635 obj.AddPropertyF("start", "%" Px "", start()); | 619 obj.AddPropertyF("start", "%" Px "", start()); |
636 obj.AddPropertyF("end", "%" Px "", end()); | 620 obj.AddPropertyF("end", "%" Px "", end()); |
637 { | 621 { |
638 // Generate a fake function entry. | 622 // Generate a fake function entry. |
639 JSONObject func(&obj, "function"); | 623 JSONObject func(&obj, "function"); |
640 ASSERT(profile_function_ != NULL); | 624 ASSERT(profile_function_ != NULL); |
641 profile_function_->PrintToJSONObject(&func); | 625 profile_function_->PrintToJSONObject(&func); |
642 } | 626 } |
643 } | 627 } |
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1387 return (*b)->count() - (*a)->count(); | 1371 return (*b)->count() - (*a)->count(); |
1388 } | 1372 } |
1389 | 1373 |
1390 const intptr_t profile_function_table_index_; | 1374 const intptr_t profile_function_table_index_; |
1391 intptr_t count_; | 1375 intptr_t count_; |
1392 ZoneGrowableArray<ProfileFunctionTrieNode*> children_; | 1376 ZoneGrowableArray<ProfileFunctionTrieNode*> children_; |
1393 ZoneGrowableArray<ProfileFunctionTrieNodeCode>* code_objects_; | 1377 ZoneGrowableArray<ProfileFunctionTrieNodeCode>* code_objects_; |
1394 }; | 1378 }; |
1395 | 1379 |
1396 | 1380 |
1397 class ProfileFunctionExclusiveTrieBuilder : public SampleVisitor { | 1381 class ProfileFunctionTrieBuilder : public SampleVisitor { |
1398 public: | 1382 public: |
1399 ProfileFunctionExclusiveTrieBuilder(Isolate* isolate, | 1383 ProfileFunctionTrieBuilder(Isolate* isolate, |
1400 CodeRegionTable* live_code_table, | 1384 CodeRegionTable* live_code_table, |
1401 CodeRegionTable* dead_code_table, | 1385 CodeRegionTable* dead_code_table, |
1402 CodeRegionTable* tag_code_table, | 1386 CodeRegionTable* tag_code_table, |
1403 ProfileFunctionTable* function_table) | 1387 ProfileFunctionTable* function_table) |
1404 : SampleVisitor(isolate), | 1388 : SampleVisitor(isolate), |
1405 live_code_table_(live_code_table), | 1389 live_code_table_(live_code_table), |
1406 dead_code_table_(dead_code_table), | 1390 dead_code_table_(dead_code_table), |
1407 tag_code_table_(tag_code_table), | 1391 tag_code_table_(tag_code_table), |
1408 function_table_(function_table), | 1392 function_table_(function_table), |
| 1393 inclusive_(false), |
1409 trace_(false), | 1394 trace_(false), |
1410 trace_code_filter_(NULL) { | 1395 trace_code_filter_(NULL) { |
1411 ASSERT(live_code_table_ != NULL); | 1396 ASSERT(live_code_table_ != NULL); |
1412 ASSERT(dead_code_table_ != NULL); | 1397 ASSERT(dead_code_table_ != NULL); |
1413 ASSERT(tag_code_table_ != NULL); | 1398 ASSERT(tag_code_table_ != NULL); |
1414 ASSERT(function_table_ != NULL); | 1399 ASSERT(function_table_ != NULL); |
1415 set_tag_order(ProfilerService::kUserVM); | 1400 set_tag_order(ProfilerService::kUserVM); |
1416 | 1401 |
1417 intptr_t root_index = tag_code_table_->FindIndex(0); | 1402 intptr_t root_index = tag_code_table_->FindIndex(0); |
1418 // Verify that the "0" tag does exist. | 1403 // Verify that the "0" tag does exist. |
1419 ASSERT(root_index >= 0); | 1404 ASSERT(root_index >= 0); |
1420 CodeRegion* region = tag_code_table_->At(root_index); | 1405 CodeRegion* region = tag_code_table_->At(root_index); |
1421 ASSERT(region != NULL); | 1406 ASSERT(region != NULL); |
| 1407 ProfileFunction* function = region->function(); |
| 1408 ASSERT(function != NULL); |
1422 | 1409 |
1423 ProfileFunction* function = region->function(); | 1410 exclusive_root_ = new ProfileFunctionTrieNode(function->index()); |
1424 root_ = new ProfileFunctionTrieNode(function->index()); | 1411 inclusive_root_ = new ProfileFunctionTrieNode(function->index()); |
1425 } | 1412 } |
1426 | 1413 |
1427 void VisitSample(Sample* sample) { | 1414 void VisitSample(Sample* sample) { |
| 1415 inclusive_ = false; |
| 1416 ProcessSampleExclusive(sample); |
| 1417 inclusive_ = true; |
| 1418 ProcessSampleInclusive(sample); |
| 1419 } |
| 1420 |
| 1421 ProfileFunctionTrieNode* exclusive_root() const { |
| 1422 return exclusive_root_; |
| 1423 } |
| 1424 |
| 1425 ProfileFunctionTrieNode* inclusive_root() const { |
| 1426 return inclusive_root_; |
| 1427 } |
| 1428 |
| 1429 ProfilerService::TagOrder tag_order() const { |
| 1430 return tag_order_; |
| 1431 } |
| 1432 |
| 1433 void set_tag_order(ProfilerService::TagOrder tag_order) { |
| 1434 tag_order_ = tag_order; |
| 1435 } |
| 1436 |
| 1437 private: |
| 1438 void ProcessSampleInclusive(Sample* sample) { |
1428 // Give the root a tick. | 1439 // Give the root a tick. |
1429 root_->Tick(); | 1440 inclusive_root_->Tick(); |
1430 ProfileFunctionTrieNode* current = root_; | 1441 ProfileFunctionTrieNode* current = inclusive_root_; |
1431 current = ProcessTags(sample, current); | 1442 current = ProcessTags(sample, current); |
1432 // Walk the sampled PCs. | 1443 // Walk the sampled PCs. |
1433 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { | 1444 for (intptr_t i = FLAG_profile_depth - 1; i >= 0; i--) { |
1434 if (sample->At(i) == 0) { | 1445 if (sample->At(i) == 0) { |
1435 break; | 1446 continue; |
1436 } | 1447 } |
1437 // If we aren't sampled out of an exit frame and this is the top | 1448 // If we aren't sampled out of an exit frame and this is the top |
1438 // frame. | 1449 // frame. |
1439 bool exclusive_tick = (i == 0) && !sample->exit_frame_sample(); | 1450 bool exclusive_tick = (i == 0) && !sample->exit_frame_sample(); |
1440 current = ProcessPC(sample->At(i), sample->timestamp(), current, | 1451 current = ProcessPC(sample->At(i), sample->timestamp(), current, |
1441 visited(), exclusive_tick, | 1452 visited(), exclusive_tick, |
1442 sample->missing_frame_inserted()); | 1453 sample->missing_frame_inserted()); |
1443 } | 1454 } |
1444 } | 1455 } |
1445 | 1456 |
1446 ProfileFunctionTrieNode* root() const { | 1457 void ProcessSampleExclusive(Sample* sample) { |
1447 return root_; | 1458 // Give the root a tick. |
| 1459 exclusive_root_->Tick(); |
| 1460 ProfileFunctionTrieNode* current = exclusive_root_; |
| 1461 current = ProcessTags(sample, current); |
| 1462 // Walk the sampled PCs. |
| 1463 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { |
| 1464 if (sample->At(i) == 0) { |
| 1465 break; |
| 1466 } |
| 1467 // If we aren't sampled out of an exit frame and this is the top |
| 1468 // frame. |
| 1469 bool exclusive_tick = (i == 0) && !sample->exit_frame_sample(); |
| 1470 current = ProcessPC(sample->At(i), sample->timestamp(), current, |
| 1471 visited(), exclusive_tick, |
| 1472 sample->missing_frame_inserted()); |
| 1473 } |
1448 } | 1474 } |
1449 | 1475 |
1450 ProfilerService::TagOrder tag_order() const { | |
1451 return tag_order_; | |
1452 } | |
1453 | |
1454 void set_tag_order(ProfilerService::TagOrder tag_order) { | |
1455 tag_order_ = tag_order; | |
1456 } | |
1457 | |
1458 private: | |
1459 ProfileFunctionTrieNode* ProcessUserTags(Sample* sample, | 1476 ProfileFunctionTrieNode* ProcessUserTags(Sample* sample, |
1460 ProfileFunctionTrieNode* current) { | 1477 ProfileFunctionTrieNode* current) { |
1461 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); | 1478 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); |
1462 if (user_tag_index >= 0) { | 1479 if (user_tag_index >= 0) { |
1463 current = current->GetChild(user_tag_index); | 1480 current = current->GetChild(user_tag_index); |
1464 // Give the tag a tick. | 1481 // Give the tag a tick. |
1465 current->Tick(); | 1482 current->Tick(); |
1466 } | 1483 } |
1467 return current; | 1484 return current; |
1468 } | 1485 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1562 code.GetInlinedFunctionsAt(offset, &inlined_functions); | 1579 code.GetInlinedFunctionsAt(offset, &inlined_functions); |
1563 } | 1580 } |
1564 if (code.IsNull() || (inlined_functions.length() == 0)) { | 1581 if (code.IsNull() || (inlined_functions.length() == 0)) { |
1565 // No inlined functions. | 1582 // No inlined functions. |
1566 ProfileFunction* function = region->function(); | 1583 ProfileFunction* function = region->function(); |
1567 ASSERT(function != NULL); | 1584 ASSERT(function != NULL); |
1568 if (trace_) { | 1585 if (trace_) { |
1569 OS::Print("[%" Px "] X - %s (%s)\n", | 1586 OS::Print("[%" Px "] X - %s (%s)\n", |
1570 pc, function->name(), region_name); | 1587 pc, function->name(), region_name); |
1571 } | 1588 } |
1572 function->Tick(exclusive, exclusive ? -1 : inclusive_serial); | 1589 if (!inclusive_) { |
| 1590 function->Tick(exclusive, exclusive ? -1 : inclusive_serial); |
| 1591 } |
1573 current = current->GetChild(function->index()); | 1592 current = current->GetChild(function->index()); |
1574 current->AddCodeObjectIndex(code_index); | 1593 current->AddCodeObjectIndex(code_index); |
1575 current->Tick(); | 1594 current->Tick(); |
1576 if ((trace_code_filter_ != NULL) && | 1595 if ((trace_code_filter_ != NULL) && |
1577 (strstr(region_name, trace_code_filter_) != NULL)) { | 1596 (strstr(region_name, trace_code_filter_) != NULL)) { |
1578 trace_ = true; | 1597 trace_ = true; |
1579 OS::Print("Tracing from: %" Px " [%s] ", pc, | 1598 OS::Print("Tracing from: %" Px " [%s] ", pc, |
1580 missing_frame_inserted ? "INSERTED" : ""); | 1599 missing_frame_inserted ? "INSERTED" : ""); |
1581 Dump(current); | 1600 Dump(current); |
1582 } | 1601 } |
1583 return current; | 1602 return current; |
1584 } | 1603 } |
1585 | 1604 |
1586 | 1605 if (inclusive_) { |
1587 for (intptr_t i = 0; i < inlined_functions.length(); i++) { | 1606 for (intptr_t i = inlined_functions.length() - 1; i >= 0; i--) { |
1588 Function* inlined_function = inlined_functions[i]; | 1607 Function* inlined_function = inlined_functions[i]; |
1589 ASSERT(inlined_function != NULL); | 1608 ASSERT(inlined_function != NULL); |
1590 ASSERT(!inlined_function->IsNull()); | 1609 ASSERT(!inlined_function->IsNull()); |
1591 const char* inline_name = inlined_function->ToQualifiedCString(); | 1610 current = ProcessInlinedFunction( |
1592 if (trace_) { | 1611 inlined_function, current, inclusive_serial, exclusive, code_index); |
1593 OS::Print("[%" Px "] %" Pd " - %s (%s)\n", | 1612 exclusive = false; |
| 1613 } |
| 1614 } else { |
| 1615 for (intptr_t i = 0; i < inlined_functions.length(); i++) { |
| 1616 Function* inlined_function = inlined_functions[i]; |
| 1617 ASSERT(inlined_function != NULL); |
| 1618 ASSERT(!inlined_function->IsNull()); |
| 1619 const char* inline_name = inlined_function->ToQualifiedCString(); |
| 1620 if (trace_) { |
| 1621 OS::Print("[%" Px "] %" Pd " - %s (%s)\n", |
1594 pc, i, inline_name, region_name); | 1622 pc, i, inline_name, region_name); |
1595 } | 1623 } |
1596 ProfileFunction* function = | 1624 current = ProcessInlinedFunction( |
1597 function_table_->LookupOrAdd(*inlined_function); | 1625 inlined_function, current, inclusive_serial, exclusive, code_index); |
1598 ASSERT(function != NULL); | 1626 exclusive = false; |
1599 function->AddCodeObjectIndex(code_index); | 1627 if ((trace_code_filter_ != NULL) && |
1600 function->Tick(exclusive, exclusive ? -1 : inclusive_serial); | 1628 (strstr(region_name, trace_code_filter_) != NULL)) { |
1601 exclusive = false; | 1629 trace_ = true; |
1602 current = current->GetChild(function->index()); | 1630 OS::Print("Tracing from: %" Px " [%s] ", |
1603 current->AddCodeObjectIndex(code_index); | 1631 pc, missing_frame_inserted ? "INSERTED" : ""); |
1604 current->Tick(); | 1632 Dump(current); |
1605 if ((trace_code_filter_ != NULL) && | 1633 } |
1606 (strstr(region_name, trace_code_filter_) != NULL)) { | |
1607 trace_ = true; | |
1608 OS::Print("Tracing from: %" Px " [%s] ", | |
1609 pc, missing_frame_inserted ? "INSERTED" : ""); | |
1610 Dump(current); | |
1611 } | 1634 } |
1612 } | 1635 } |
| 1636 |
1613 return current; | 1637 return current; |
1614 } | 1638 } |
1615 | 1639 |
| 1640 ProfileFunctionTrieNode* ProcessInlinedFunction( |
| 1641 Function* inlined_function, |
| 1642 ProfileFunctionTrieNode* current, |
| 1643 intptr_t inclusive_serial, |
| 1644 bool exclusive, |
| 1645 intptr_t code_index) { |
| 1646 ProfileFunction* function = |
| 1647 function_table_->LookupOrAdd(*inlined_function); |
| 1648 ASSERT(function != NULL); |
| 1649 function->AddCodeObjectIndex(code_index); |
| 1650 function->Tick(exclusive, exclusive ? -1 : inclusive_serial); |
| 1651 current = current->GetChild(function->index()); |
| 1652 current->AddCodeObjectIndex(code_index); |
| 1653 current->Tick(); |
| 1654 return current; |
| 1655 } |
| 1656 |
1616 CodeRegion* FindCodeObject(uword pc, int64_t timestamp) const { | 1657 CodeRegion* FindCodeObject(uword pc, int64_t timestamp) const { |
1617 intptr_t index = live_code_table_->FindIndex(pc); | 1658 intptr_t index = live_code_table_->FindIndex(pc); |
1618 if (index < 0) { | 1659 if (index < 0) { |
1619 return NULL; | 1660 return NULL; |
1620 } | 1661 } |
1621 CodeRegion* region = live_code_table_->At(index); | 1662 CodeRegion* region = live_code_table_->At(index); |
1622 ASSERT(region->contains(pc)); | 1663 ASSERT(region->contains(pc)); |
1623 if (region->compile_timestamp() > timestamp) { | 1664 if (region->compile_timestamp() > timestamp) { |
1624 // Overwritten code, find in dead code table. | 1665 // Overwritten code, find in dead code table. |
1625 index = dead_code_table_->FindIndex(pc); | 1666 index = dead_code_table_->FindIndex(pc); |
1626 if (index < 0) { | 1667 if (index < 0) { |
1627 return NULL; | 1668 return NULL; |
1628 } | 1669 } |
1629 region = dead_code_table_->At(index); | 1670 region = dead_code_table_->At(index); |
1630 ASSERT(region->contains(pc)); | 1671 ASSERT(region->contains(pc)); |
1631 ASSERT(region->compile_timestamp() <= timestamp); | 1672 ASSERT(region->compile_timestamp() <= timestamp); |
1632 return region; | 1673 return region; |
1633 } | 1674 } |
1634 ASSERT(region->compile_timestamp() <= timestamp); | 1675 ASSERT(region->compile_timestamp() <= timestamp); |
1635 return region; | 1676 return region; |
1636 } | 1677 } |
1637 | 1678 |
1638 ProfilerService::TagOrder tag_order_; | 1679 ProfilerService::TagOrder tag_order_; |
1639 ProfileFunctionTrieNode* root_; | 1680 ProfileFunctionTrieNode* exclusive_root_; |
| 1681 ProfileFunctionTrieNode* inclusive_root_; |
1640 CodeRegionTable* live_code_table_; | 1682 CodeRegionTable* live_code_table_; |
1641 CodeRegionTable* dead_code_table_; | 1683 CodeRegionTable* dead_code_table_; |
1642 CodeRegionTable* tag_code_table_; | 1684 CodeRegionTable* tag_code_table_; |
1643 ProfileFunctionTable* function_table_; | 1685 ProfileFunctionTable* function_table_; |
| 1686 bool inclusive_; |
1644 bool trace_; | 1687 bool trace_; |
1645 const char* trace_code_filter_; | 1688 const char* trace_code_filter_; |
1646 }; | 1689 }; |
1647 | 1690 |
1648 | 1691 |
1649 class CodeRegionTrieNode : public ZoneAllocated { | 1692 class CodeRegionTrieNode : public ZoneAllocated { |
1650 public: | 1693 public: |
1651 explicit CodeRegionTrieNode(intptr_t code_region_index) | 1694 explicit CodeRegionTrieNode(intptr_t code_region_index) |
1652 : code_region_index_(code_region_index), | 1695 : code_region_index_(code_region_index), |
1653 count_(0), | 1696 count_(0), |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1731 ASSERT(b != NULL); | 1774 ASSERT(b != NULL); |
1732 return (*b)->count() - (*a)->count(); | 1775 return (*b)->count() - (*a)->count(); |
1733 } | 1776 } |
1734 | 1777 |
1735 const intptr_t code_region_index_; | 1778 const intptr_t code_region_index_; |
1736 intptr_t count_; | 1779 intptr_t count_; |
1737 ZoneGrowableArray<CodeRegionTrieNode*>* children_; | 1780 ZoneGrowableArray<CodeRegionTrieNode*>* children_; |
1738 }; | 1781 }; |
1739 | 1782 |
1740 | 1783 |
1741 class CodeRegionExclusiveTrieBuilder : public SampleVisitor { | 1784 class CodeRegionTrieBuilder : public SampleVisitor { |
1742 public: | 1785 public: |
1743 CodeRegionExclusiveTrieBuilder(Isolate* isolate, | 1786 CodeRegionTrieBuilder(Isolate* isolate, |
1744 CodeRegionTable* live_code_table, | 1787 CodeRegionTable* live_code_table, |
1745 CodeRegionTable* dead_code_table, | 1788 CodeRegionTable* dead_code_table, |
1746 CodeRegionTable* tag_code_table) | 1789 CodeRegionTable* tag_code_table) |
1747 : SampleVisitor(isolate), | 1790 : SampleVisitor(isolate), |
1748 live_code_table_(live_code_table), | 1791 live_code_table_(live_code_table), |
1749 dead_code_table_(dead_code_table), | 1792 dead_code_table_(dead_code_table), |
1750 tag_code_table_(tag_code_table) { | 1793 tag_code_table_(tag_code_table) { |
1751 ASSERT(live_code_table_ != NULL); | 1794 ASSERT(live_code_table_ != NULL); |
1752 ASSERT(dead_code_table_ != NULL); | 1795 ASSERT(dead_code_table_ != NULL); |
1753 ASSERT(tag_code_table_ != NULL); | 1796 ASSERT(tag_code_table_ != NULL); |
1754 set_tag_order(ProfilerService::kUserVM); | 1797 set_tag_order(ProfilerService::kUserVM); |
1755 | 1798 |
1756 intptr_t root_index = tag_code_table_->FindIndex(0); | 1799 intptr_t root_index = tag_code_table_->FindIndex(0); |
1757 // Verify that the "0" (root) tag does exist. | 1800 // Verify that the "0" (root) tag does exist. |
1758 ASSERT(root_index >= 0); | 1801 ASSERT(root_index >= 0); |
1759 CodeRegion* region = tag_code_table_->At(root_index); | 1802 CodeRegion* region = tag_code_table_->At(root_index); |
1760 ASSERT(region != NULL); | 1803 ASSERT(region != NULL); |
1761 root_ = new CodeRegionTrieNode(region->code_table_index()); | 1804 |
| 1805 exclusive_root_ = new CodeRegionTrieNode(region->code_table_index()); |
| 1806 inclusive_root_ = new CodeRegionTrieNode(region->code_table_index()); |
1762 } | 1807 } |
1763 | 1808 |
1764 void VisitSample(Sample* sample) { | 1809 void VisitSample(Sample* sample) { |
| 1810 ProcessSampleExclusive(sample); |
| 1811 ProcessSampleInclusive(sample); |
| 1812 } |
| 1813 |
| 1814 CodeRegionTrieNode* inclusive_root() const { |
| 1815 return inclusive_root_; |
| 1816 } |
| 1817 |
| 1818 CodeRegionTrieNode* exclusive_root() const { |
| 1819 return exclusive_root_; |
| 1820 } |
| 1821 |
| 1822 ProfilerService::TagOrder tag_order() const { |
| 1823 return tag_order_; |
| 1824 } |
| 1825 |
| 1826 void set_tag_order(ProfilerService::TagOrder tag_order) { |
| 1827 tag_order_ = tag_order; |
| 1828 } |
| 1829 |
| 1830 private: |
| 1831 void ProcessSampleInclusive(Sample* sample) { |
1765 // Give the root a tick. | 1832 // Give the root a tick. |
1766 root_->Tick(); | 1833 inclusive_root_->Tick(); |
1767 CodeRegionTrieNode* current = root_; | 1834 CodeRegionTrieNode* current = inclusive_root_; |
1768 current = ProcessTags(sample, current); | 1835 current = ProcessTags(sample, current); |
1769 // Walk the sampled PCs. | 1836 // Walk the sampled PCs. |
1770 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { | 1837 for (intptr_t i = FLAG_profile_depth - 1; i >= 0; i--) { |
1771 if (sample->At(i) == 0) { | 1838 if (sample->At(i) == 0) { |
1772 break; | 1839 continue; |
1773 } | 1840 } |
1774 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp()); | 1841 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp()); |
1775 if (index < 0) { | 1842 if (index < 0) { |
1776 continue; | 1843 continue; |
1777 } | 1844 } |
1778 current = current->GetChild(index); | 1845 current = current->GetChild(index); |
1779 current->Tick(); | 1846 current->Tick(); |
1780 } | 1847 } |
1781 } | 1848 } |
1782 | 1849 |
1783 CodeRegionTrieNode* root() const { | 1850 void ProcessSampleExclusive(Sample* sample) { |
1784 return root_; | 1851 // Give the root a tick. |
| 1852 exclusive_root_->Tick(); |
| 1853 CodeRegionTrieNode* current = exclusive_root_; |
| 1854 current = ProcessTags(sample, current); |
| 1855 // Walk the sampled PCs. |
| 1856 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { |
| 1857 if (sample->At(i) == 0) { |
| 1858 break; |
| 1859 } |
| 1860 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp()); |
| 1861 if (index < 0) { |
| 1862 continue; |
| 1863 } |
| 1864 current = current->GetChild(index); |
| 1865 current->Tick(); |
| 1866 } |
1785 } | 1867 } |
1786 | 1868 |
1787 ProfilerService::TagOrder tag_order() const { | |
1788 return tag_order_; | |
1789 } | |
1790 | |
1791 void set_tag_order(ProfilerService::TagOrder tag_order) { | |
1792 tag_order_ = tag_order; | |
1793 } | |
1794 | |
1795 private: | |
1796 CodeRegionTrieNode* ProcessUserTags(Sample* sample, | 1869 CodeRegionTrieNode* ProcessUserTags(Sample* sample, |
1797 CodeRegionTrieNode* current) { | 1870 CodeRegionTrieNode* current) { |
1798 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); | 1871 intptr_t user_tag_index = FindTagIndex(sample->user_tag()); |
1799 if (user_tag_index >= 0) { | 1872 if (user_tag_index >= 0) { |
1800 current = current->GetChild(user_tag_index); | 1873 current = current->GetChild(user_tag_index); |
1801 // Give the tag a tick. | 1874 // Give the tag a tick. |
1802 current->Tick(); | 1875 current->Tick(); |
1803 } | 1876 } |
1804 return current; | 1877 return current; |
1805 } | 1878 } |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1890 ASSERT(region->contains(pc)); | 1963 ASSERT(region->contains(pc)); |
1891 if (region->compile_timestamp() > timestamp) { | 1964 if (region->compile_timestamp() > timestamp) { |
1892 // Overwritten code, find in dead code table. | 1965 // Overwritten code, find in dead code table. |
1893 return FindDeadIndex(pc, timestamp); | 1966 return FindDeadIndex(pc, timestamp); |
1894 } | 1967 } |
1895 ASSERT(region->compile_timestamp() <= timestamp); | 1968 ASSERT(region->compile_timestamp() <= timestamp); |
1896 return region->code_table_index(); | 1969 return region->code_table_index(); |
1897 } | 1970 } |
1898 | 1971 |
1899 ProfilerService::TagOrder tag_order_; | 1972 ProfilerService::TagOrder tag_order_; |
1900 CodeRegionTrieNode* root_; | 1973 CodeRegionTrieNode* exclusive_root_; |
| 1974 CodeRegionTrieNode* inclusive_root_; |
1901 CodeRegionTable* live_code_table_; | 1975 CodeRegionTable* live_code_table_; |
1902 CodeRegionTable* dead_code_table_; | 1976 CodeRegionTable* dead_code_table_; |
1903 CodeRegionTable* tag_code_table_; | 1977 CodeRegionTable* tag_code_table_; |
1904 }; | 1978 }; |
1905 | 1979 |
1906 | 1980 |
1907 void ProfilerService::PrintJSON(JSONStream* stream, TagOrder tag_order) { | 1981 void ProfilerService::PrintJSON(JSONStream* stream, TagOrder tag_order) { |
1908 Isolate* isolate = Isolate::Current(); | 1982 Isolate* isolate = Isolate::Current(); |
1909 // Disable profile interrupts while processing the buffer. | 1983 // Disable profile interrupts while processing the buffer. |
1910 Profiler::EndExecution(isolate); | 1984 Profiler::EndExecution(isolate); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1976 CodeRegionFunctionMapper mapper(isolate, &live_code_table, | 2050 CodeRegionFunctionMapper mapper(isolate, &live_code_table, |
1977 &dead_code_table, | 2051 &dead_code_table, |
1978 &tag_code_table, | 2052 &tag_code_table, |
1979 &function_table); | 2053 &function_table); |
1980 mapper.Map(); | 2054 mapper.Map(); |
1981 } | 2055 } |
1982 if (FLAG_trace_profiler) { | 2056 if (FLAG_trace_profiler) { |
1983 intptr_t total_functions = function_table.Length(); | 2057 intptr_t total_functions = function_table.Length(); |
1984 OS::Print("FunctionTable: size=%" Pd "\n", total_functions); | 2058 OS::Print("FunctionTable: size=%" Pd "\n", total_functions); |
1985 } | 2059 } |
1986 CodeRegionExclusiveTrieBuilder code_trie_builder(isolate, | 2060 CodeRegionTrieBuilder code_trie_builder(isolate, |
1987 &live_code_table, | 2061 &live_code_table, |
1988 &dead_code_table, | 2062 &dead_code_table, |
1989 &tag_code_table); | 2063 &tag_code_table); |
1990 code_trie_builder.set_tag_order(tag_order); | 2064 code_trie_builder.set_tag_order(tag_order); |
1991 { | 2065 { |
1992 // Build CodeRegion trie. | 2066 // Build CodeRegion trie. |
1993 ScopeTimer sw("CodeRegionExclusiveTrieBuilder", FLAG_trace_profiler); | 2067 ScopeTimer sw("CodeRegionTrieBuilder", FLAG_trace_profiler); |
1994 sample_buffer->VisitSamples(&code_trie_builder); | 2068 sample_buffer->VisitSamples(&code_trie_builder); |
1995 code_trie_builder.root()->SortByCount(); | 2069 code_trie_builder.exclusive_root()->SortByCount(); |
| 2070 code_trie_builder.inclusive_root()->SortByCount(); |
1996 } | 2071 } |
1997 ProfileFunctionExclusiveTrieBuilder | 2072 ProfileFunctionTrieBuilder function_trie_builder(isolate, |
1998 function_trie_builder(isolate, | 2073 &live_code_table, |
1999 &live_code_table, | 2074 &dead_code_table, |
2000 &dead_code_table, | 2075 &tag_code_table, |
2001 &tag_code_table, | 2076 &function_table); |
2002 &function_table); | |
2003 function_trie_builder.set_tag_order(tag_order); | 2077 function_trie_builder.set_tag_order(tag_order); |
2004 { | 2078 { |
2005 // Build ProfileFunction trie. | 2079 // Build ProfileFunction trie. |
2006 ScopeTimer sw("ProfileFunctionExclusiveTrieBuilder", | 2080 ScopeTimer sw("ProfileFunctionTrieBuilder", |
2007 FLAG_trace_profiler); | 2081 FLAG_trace_profiler); |
2008 sample_buffer->VisitSamples(&function_trie_builder); | 2082 sample_buffer->VisitSamples(&function_trie_builder); |
2009 function_trie_builder.root()->SortByCount(); | 2083 function_trie_builder.exclusive_root()->SortByCount(); |
| 2084 function_trie_builder.inclusive_root()->SortByCount(); |
2010 } | 2085 } |
2011 { | 2086 { |
2012 ScopeTimer sw("CodeTableStream", FLAG_trace_profiler); | 2087 ScopeTimer sw("CpuProfileJSONStream", FLAG_trace_profiler); |
2013 // Serialize to JSON. | 2088 // Serialize to JSON. |
2014 JSONObject obj(stream); | 2089 JSONObject obj(stream); |
2015 obj.AddProperty("type", "_CpuProfile"); | 2090 obj.AddProperty("type", "_CpuProfile"); |
2016 obj.AddProperty("sampleCount", samples); | 2091 obj.AddProperty("sampleCount", samples); |
2017 obj.AddProperty("samplePeriod", | 2092 obj.AddProperty("samplePeriod", |
2018 static_cast<intptr_t>(FLAG_profile_period)); | 2093 static_cast<intptr_t>(FLAG_profile_period)); |
2019 obj.AddProperty("stackDepth", | 2094 obj.AddProperty("stackDepth", |
2020 static_cast<intptr_t>(FLAG_profile_depth)); | 2095 static_cast<intptr_t>(FLAG_profile_depth)); |
2021 obj.AddProperty("timeSpan", | 2096 obj.AddProperty("timeSpan", |
2022 MicrosecondsToSeconds(builder.TimeDeltaMicros())); | 2097 MicrosecondsToSeconds(builder.TimeDeltaMicros())); |
2023 { | 2098 { |
2024 JSONArray exclusive_trie(&obj, "exclusiveCodeTrie"); | 2099 JSONArray code_trie(&obj, "exclusiveCodeTrie"); |
2025 CodeRegionTrieNode* root = code_trie_builder.root(); | 2100 CodeRegionTrieNode* root = code_trie_builder.exclusive_root(); |
2026 ASSERT(root != NULL); | 2101 ASSERT(root != NULL); |
2027 root->PrintToJSONArray(&exclusive_trie); | 2102 root->PrintToJSONArray(&code_trie); |
| 2103 } |
| 2104 { |
| 2105 JSONArray code_trie(&obj, "inclusiveCodeTrie"); |
| 2106 CodeRegionTrieNode* root = code_trie_builder.inclusive_root(); |
| 2107 ASSERT(root != NULL); |
| 2108 root->PrintToJSONArray(&code_trie); |
2028 } | 2109 } |
2029 { | 2110 { |
2030 JSONArray function_trie(&obj, "exclusiveFunctionTrie"); | 2111 JSONArray function_trie(&obj, "exclusiveFunctionTrie"); |
2031 ProfileFunctionTrieNode* root = function_trie_builder.root(); | 2112 ProfileFunctionTrieNode* root = |
| 2113 function_trie_builder.exclusive_root(); |
2032 ASSERT(root != NULL); | 2114 ASSERT(root != NULL); |
2033 root->PrintToJSONArray(&function_trie); | 2115 root->PrintToJSONArray(&function_trie); |
2034 } | 2116 } |
| 2117 { |
| 2118 JSONArray function_trie(&obj, "inclusiveFunctionTrie"); |
| 2119 ProfileFunctionTrieNode* root = |
| 2120 function_trie_builder.inclusive_root(); |
| 2121 ASSERT(root != NULL); |
| 2122 root->PrintToJSONArray(&function_trie); |
| 2123 } |
2035 { | 2124 { |
2036 JSONArray codes(&obj, "codes"); | 2125 JSONArray codes(&obj, "codes"); |
2037 for (intptr_t i = 0; i < live_code_table.Length(); i++) { | 2126 for (intptr_t i = 0; i < live_code_table.Length(); i++) { |
2038 CodeRegion* region = live_code_table.At(i); | 2127 CodeRegion* region = live_code_table.At(i); |
2039 ASSERT(region != NULL); | 2128 ASSERT(region != NULL); |
2040 region->PrintToJSONArray(&codes); | 2129 region->PrintToJSONArray(&codes); |
2041 } | 2130 } |
2042 for (intptr_t i = 0; i < dead_code_table.Length(); i++) { | 2131 for (intptr_t i = 0; i < dead_code_table.Length(); i++) { |
2043 CodeRegion* region = dead_code_table.At(i); | 2132 CodeRegion* region = dead_code_table.At(i); |
2044 ASSERT(region != NULL); | 2133 ASSERT(region != NULL); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2083 ASSERT(sample_buffer != NULL); | 2172 ASSERT(sample_buffer != NULL); |
2084 | 2173 |
2085 ClearProfileVisitor clear_profile(isolate); | 2174 ClearProfileVisitor clear_profile(isolate); |
2086 sample_buffer->VisitSamples(&clear_profile); | 2175 sample_buffer->VisitSamples(&clear_profile); |
2087 | 2176 |
2088 // Enable profile interrupts. | 2177 // Enable profile interrupts. |
2089 Profiler::BeginExecution(isolate); | 2178 Profiler::BeginExecution(isolate); |
2090 } | 2179 } |
2091 | 2180 |
2092 } // namespace dart | 2181 } // namespace dart |
OLD | NEW |