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/hash_map.h" | 8 #include "vm/hash_map.h" |
9 #include "vm/log.h" | 9 #include "vm/log.h" |
10 #include "vm/malloc_hooks.h" | |
10 #include "vm/native_symbol.h" | 11 #include "vm/native_symbol.h" |
11 #include "vm/object.h" | 12 #include "vm/object.h" |
12 #include "vm/os.h" | 13 #include "vm/os.h" |
13 #include "vm/profiler.h" | 14 #include "vm/profiler.h" |
14 #include "vm/reusable_handles.h" | 15 #include "vm/reusable_handles.h" |
15 #include "vm/scope_timer.h" | 16 #include "vm/scope_timer.h" |
16 | 17 |
17 namespace dart { | 18 namespace dart { |
18 | 19 |
19 DECLARE_FLAG(int, max_profile_depth); | 20 DECLARE_FLAG(int, max_profile_depth); |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
223 func->AddProperty("name", name()); | 224 func->AddProperty("name", name()); |
224 func->AddProperty("_kind", KindToCString(kind())); | 225 func->AddProperty("_kind", KindToCString(kind())); |
225 } | 226 } |
226 | 227 |
227 | 228 |
228 void ProfileFunction::PrintToJSONArray(JSONArray* functions) { | 229 void ProfileFunction::PrintToJSONArray(JSONArray* functions) { |
229 JSONObject obj(functions); | 230 JSONObject obj(functions); |
230 obj.AddProperty("kind", KindToCString(kind())); | 231 obj.AddProperty("kind", KindToCString(kind())); |
231 obj.AddPropertyF("inclusiveTicks", "%" Pd "", inclusive_ticks()); | 232 obj.AddPropertyF("inclusiveTicks", "%" Pd "", inclusive_ticks()); |
232 obj.AddPropertyF("exclusiveTicks", "%" Pd "", exclusive_ticks()); | 233 obj.AddPropertyF("exclusiveTicks", "%" Pd "", exclusive_ticks()); |
234 | |
233 if (kind() == kDartFunction) { | 235 if (kind() == kDartFunction) { |
234 ASSERT(!function_.IsNull()); | 236 ASSERT(!function_.IsNull()); |
235 obj.AddProperty("function", function_); | 237 obj.AddProperty("function", function_); |
236 } else { | 238 } else { |
237 JSONObject func(&obj, "function"); | 239 JSONObject func(&obj, "function"); |
238 PrintToJSONObject(&func); | 240 PrintToJSONObject(&func); |
239 } | 241 } |
240 { | 242 { |
241 JSONArray codes(&obj, "codes"); | 243 JSONArray codes(&obj, "codes"); |
242 for (intptr_t i = 0; i < profile_codes_.length(); i++) { | 244 for (intptr_t i = 0; i < profile_codes_.length(); i++) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 // If exclusive is set, tick it. | 350 // If exclusive is set, tick it. |
349 if (exclusive) { | 351 if (exclusive) { |
350 exclusive_ticks_++; | 352 exclusive_ticks_++; |
351 TickAddress(pc, true); | 353 TickAddress(pc, true); |
352 } | 354 } |
353 // Fall through and tick inclusive count too. | 355 // Fall through and tick inclusive count too. |
354 if (inclusive_serial_ == serial) { | 356 if (inclusive_serial_ == serial) { |
355 // Already gave inclusive tick for this sample. | 357 // Already gave inclusive tick for this sample. |
356 return; | 358 return; |
357 } | 359 } |
360 | |
358 inclusive_serial_ = serial; | 361 inclusive_serial_ = serial; |
359 inclusive_ticks_++; | 362 inclusive_ticks_++; |
360 TickAddress(pc, false); | 363 TickAddress(pc, false); |
361 } | 364 } |
362 | 365 |
363 | 366 |
364 void ProfileCode::TickAddress(uword pc, bool exclusive) { | 367 void ProfileCode::TickAddress(uword pc, bool exclusive) { |
365 const intptr_t length = address_ticks_.length(); | 368 const intptr_t length = address_ticks_.length(); |
366 | 369 |
367 intptr_t i = 0; | 370 intptr_t i = 0; |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
856 !b->Contains(a->start()) && !b->Contains(a->end() - 1)); | 859 !b->Contains(a->start()) && !b->Contains(a->end() - 1)); |
857 } | 860 } |
858 } | 861 } |
859 } | 862 } |
860 | 863 |
861 ZoneGrowableArray<ProfileCode*> table_; | 864 ZoneGrowableArray<ProfileCode*> table_; |
862 }; | 865 }; |
863 | 866 |
864 | 867 |
865 ProfileTrieNode::ProfileTrieNode(intptr_t table_index) | 868 ProfileTrieNode::ProfileTrieNode(intptr_t table_index) |
866 : table_index_(table_index), count_(0), children_(0), frame_id_(-1) { | 869 : table_index_(table_index), |
870 count_(0), | |
871 exclusive_allocations_(0), | |
872 inclusive_allocations_(0), | |
873 children_(0), | |
874 frame_id_(-1) { | |
867 ASSERT(table_index_ >= 0); | 875 ASSERT(table_index_ >= 0); |
868 } | 876 } |
869 | 877 |
870 | 878 |
871 ProfileTrieNode::~ProfileTrieNode() {} | 879 ProfileTrieNode::~ProfileTrieNode() {} |
872 | 880 |
873 | 881 |
882 void ProfileTrieNode::Tick(ProcessedSample* sample, bool exclusive) { | |
883 count_++; | |
884 IncrementAllocation(sample->native_allocation_size_bytes(), exclusive); | |
885 } | |
886 | |
887 | |
874 void ProfileTrieNode::SortChildren() { | 888 void ProfileTrieNode::SortChildren() { |
875 children_.Sort(ProfileTrieNodeCompare); | 889 children_.Sort(ProfileTrieNodeCompare); |
876 // Recurse. | 890 // Recurse. |
877 for (intptr_t i = 0; i < children_.length(); i++) { | 891 for (intptr_t i = 0; i < children_.length(); i++) { |
878 children_[i]->SortChildren(); | 892 children_[i]->SortChildren(); |
879 } | 893 } |
880 } | 894 } |
881 | 895 |
882 | 896 |
883 intptr_t ProfileTrieNode::IndexOf(ProfileTrieNode* node) { | 897 intptr_t ProfileTrieNode::IndexOf(ProfileTrieNode* node) { |
(...skipping 13 matching lines...) Expand all Loading... | |
897 | 911 |
898 void PrintToJSONArray(JSONArray* array) const { | 912 void PrintToJSONArray(JSONArray* array) const { |
899 ASSERT(array != NULL); | 913 ASSERT(array != NULL); |
900 // Write CodeRegion index. | 914 // Write CodeRegion index. |
901 array->AddValue(table_index()); | 915 array->AddValue(table_index()); |
902 // Write count. | 916 // Write count. |
903 array->AddValue(count()); | 917 array->AddValue(count()); |
904 // Write number of children. | 918 // Write number of children. |
905 intptr_t child_count = NumChildren(); | 919 intptr_t child_count = NumChildren(); |
906 array->AddValue(child_count); | 920 array->AddValue(child_count); |
921 // Write inclusive allocations. | |
922 array->AddValue64(inclusive_allocations_); | |
923 // Write exclusive allocations. | |
924 array->AddValue64(exclusive_allocations_); | |
907 // Recurse. | 925 // Recurse. |
908 for (intptr_t i = 0; i < child_count; i++) { | 926 for (intptr_t i = 0; i < child_count; i++) { |
909 children_[i]->PrintToJSONArray(array); | 927 children_[i]->PrintToJSONArray(array); |
910 } | 928 } |
911 } | 929 } |
912 | 930 |
913 ProfileCodeTrieNode* GetChild(intptr_t child_table_index) { | 931 ProfileCodeTrieNode* GetChild(intptr_t child_table_index) { |
914 const intptr_t length = NumChildren(); | 932 const intptr_t length = NumChildren(); |
915 intptr_t i = 0; | 933 intptr_t i = 0; |
916 while (i < length) { | 934 while (i < length) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
958 public: | 976 public: |
959 explicit ProfileFunctionTrieNode(intptr_t table_index) | 977 explicit ProfileFunctionTrieNode(intptr_t table_index) |
960 : ProfileTrieNode(table_index), code_objects_(1) {} | 978 : ProfileTrieNode(table_index), code_objects_(1) {} |
961 | 979 |
962 void PrintToJSONArray(JSONArray* array) const { | 980 void PrintToJSONArray(JSONArray* array) const { |
963 ASSERT(array != NULL); | 981 ASSERT(array != NULL); |
964 // Write CodeRegion index. | 982 // Write CodeRegion index. |
965 array->AddValue(table_index()); | 983 array->AddValue(table_index()); |
966 // Write count. | 984 // Write count. |
967 array->AddValue(count()); | 985 array->AddValue(count()); |
986 // Write inclusive allocations. | |
987 array->AddValue64(inclusive_allocations_); | |
988 // Write exclusive allocations. | |
989 array->AddValue64(exclusive_allocations_); | |
968 // Write number of code objects. | 990 // Write number of code objects. |
969 intptr_t code_count = code_objects_.length(); | 991 intptr_t code_count = code_objects_.length(); |
970 array->AddValue(code_count); | 992 array->AddValue(code_count); |
971 // Write each code object index and ticks. | 993 // Write each code object index and ticks. |
972 for (intptr_t i = 0; i < code_count; i++) { | 994 for (intptr_t i = 0; i < code_count; i++) { |
973 array->AddValue(code_objects_[i].index()); | 995 array->AddValue(code_objects_[i].index()); |
974 array->AddValue(code_objects_[i].ticks()); | 996 array->AddValue(code_objects_[i].ticks()); |
975 } | 997 } |
976 // Write number of children. | 998 // Write number of children. |
977 intptr_t child_count = children_.length(); | 999 intptr_t child_count = children_.length(); |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1316 // and tick each one. | 1338 // and tick each one. |
1317 for (intptr_t frame_index = 0; frame_index < sample->length(); | 1339 for (intptr_t frame_index = 0; frame_index < sample->length(); |
1318 frame_index++) { | 1340 frame_index++) { |
1319 const uword pc = sample->At(frame_index); | 1341 const uword pc = sample->At(frame_index); |
1320 ASSERT(pc != 0); | 1342 ASSERT(pc != 0); |
1321 ProfileCode* code = FindOrRegisterProfileCode(pc, timestamp); | 1343 ProfileCode* code = FindOrRegisterProfileCode(pc, timestamp); |
1322 ASSERT(code != NULL); | 1344 ASSERT(code != NULL); |
1323 code->Tick(pc, IsExecutingFrame(sample, frame_index), sample_index); | 1345 code->Tick(pc, IsExecutingFrame(sample, frame_index), sample_index); |
1324 } | 1346 } |
1325 | 1347 |
1326 TickExitFrame(sample->vm_tag(), sample_index); | 1348 TickExitFrame(sample->vm_tag(), sample_index, sample); |
1327 } | 1349 } |
1328 SanitizeMinMaxTimes(); | 1350 SanitizeMinMaxTimes(); |
1329 } | 1351 } |
1330 | 1352 |
1331 void FinalizeCodeIndexes() { | 1353 void FinalizeCodeIndexes() { |
1332 ScopeTimer sw("ProfileBuilder::FinalizeCodeIndexes", FLAG_trace_profiler); | 1354 ScopeTimer sw("ProfileBuilder::FinalizeCodeIndexes", FLAG_trace_profiler); |
1333 ProfileCodeTable* live_table = profile_->live_code_; | 1355 ProfileCodeTable* live_table = profile_->live_code_; |
1334 ProfileCodeTable* dead_table = profile_->dead_code_; | 1356 ProfileCodeTable* dead_table = profile_->dead_code_; |
1335 ProfileCodeTable* tag_table = profile_->tag_code_; | 1357 ProfileCodeTable* tag_table = profile_->tag_code_; |
1336 const intptr_t dead_code_index_offset = live_table->length(); | 1358 const intptr_t dead_code_index_offset = live_table->length(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1402 | 1424 |
1403 void BuildInclusiveCodeTrie(ProfileCodeTrieNode* root) { | 1425 void BuildInclusiveCodeTrie(ProfileCodeTrieNode* root) { |
1404 ScopeTimer sw("ProfileBuilder::BuildInclusiveCodeTrie", | 1426 ScopeTimer sw("ProfileBuilder::BuildInclusiveCodeTrie", |
1405 FLAG_trace_profiler); | 1427 FLAG_trace_profiler); |
1406 for (intptr_t sample_index = 0; sample_index < samples_->length(); | 1428 for (intptr_t sample_index = 0; sample_index < samples_->length(); |
1407 sample_index++) { | 1429 sample_index++) { |
1408 ProcessedSample* sample = samples_->At(sample_index); | 1430 ProcessedSample* sample = samples_->At(sample_index); |
1409 | 1431 |
1410 // Tick the root. | 1432 // Tick the root. |
1411 ProfileCodeTrieNode* current = root; | 1433 ProfileCodeTrieNode* current = root; |
1412 current->Tick(); | 1434 current->Tick(sample); |
1413 | 1435 |
1414 // VM & User tags. | 1436 // VM & User tags. |
1415 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); | 1437 current = |
1438 AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); | |
1416 | 1439 |
1417 ResetKind(); | 1440 ResetKind(); |
1418 | 1441 |
1419 // Truncated tag. | 1442 // Truncated tag. |
1420 if (sample->truncated()) { | 1443 if (sample->truncated()) { |
1421 current = AppendTruncatedTag(current); | 1444 current = AppendTruncatedTag(current, sample); |
1422 } | 1445 } |
1423 | 1446 |
1424 // Walk the sampled PCs. | 1447 // Walk the sampled PCs. |
1425 Code& code = Code::Handle(); | 1448 Code& code = Code::Handle(); |
1426 for (intptr_t frame_index = sample->length() - 1; frame_index >= 0; | 1449 for (intptr_t frame_index = sample->length() - 1; frame_index >= 0; |
1427 frame_index--) { | 1450 frame_index--) { |
1428 ASSERT(sample->At(frame_index) != 0); | 1451 ASSERT(sample->At(frame_index) != 0); |
1429 intptr_t index = | 1452 intptr_t index = |
1430 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); | 1453 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); |
1431 ASSERT(index >= 0); | 1454 ASSERT(index >= 0); |
1432 ProfileCode* profile_code = | 1455 ProfileCode* profile_code = |
1433 GetProfileCode(sample->At(frame_index), sample->timestamp()); | 1456 GetProfileCode(sample->At(frame_index), sample->timestamp()); |
1434 ASSERT(profile_code->code_table_index() == index); | 1457 ASSERT(profile_code->code_table_index() == index); |
1435 code ^= profile_code->code(); | 1458 code ^= profile_code->code(); |
1436 current = AppendKind(code, current); | 1459 current = AppendKind(code, current, sample); |
1437 current = current->GetChild(index); | 1460 current = current->GetChild(index); |
1438 current->Tick(); | 1461 current->Tick(sample, (frame_index == 0)); |
1439 } | 1462 } |
1440 | 1463 |
1441 if (!sample->first_frame_executing()) { | 1464 if (!sample->first_frame_executing()) { |
1442 current = AppendExitFrame(sample->vm_tag(), current); | 1465 current = AppendExitFrame(sample->vm_tag(), current, sample); |
1443 } | 1466 } |
1444 } | 1467 } |
1445 } | 1468 } |
1446 | 1469 |
1447 void BuildExclusiveCodeTrie(ProfileCodeTrieNode* root) { | 1470 void BuildExclusiveCodeTrie(ProfileCodeTrieNode* root) { |
1448 ScopeTimer sw("ProfileBuilder::BuildExclusiveCodeTrie", | 1471 ScopeTimer sw("ProfileBuilder::BuildExclusiveCodeTrie", |
1449 FLAG_trace_profiler); | 1472 FLAG_trace_profiler); |
1450 for (intptr_t sample_index = 0; sample_index < samples_->length(); | 1473 for (intptr_t sample_index = 0; sample_index < samples_->length(); |
1451 sample_index++) { | 1474 sample_index++) { |
1452 ProcessedSample* sample = samples_->At(sample_index); | 1475 ProcessedSample* sample = samples_->At(sample_index); |
1453 | 1476 |
1454 // Tick the root. | 1477 // Tick the root. |
1455 ProfileCodeTrieNode* current = root; | 1478 ProfileCodeTrieNode* current = root; |
1456 current->Tick(); | 1479 current->Tick(sample); |
1457 | |
1458 // VM & User tags. | 1480 // VM & User tags. |
1459 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); | 1481 current = |
1482 AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); | |
1460 | 1483 |
1461 ResetKind(); | 1484 ResetKind(); |
1462 | 1485 |
1463 if (!sample->first_frame_executing()) { | 1486 if (!sample->first_frame_executing()) { |
1464 current = AppendExitFrame(sample->vm_tag(), current); | 1487 current = AppendExitFrame(sample->vm_tag(), current, sample); |
1465 } | 1488 } |
1466 | 1489 |
1467 // Walk the sampled PCs. | 1490 // Walk the sampled PCs. |
1468 Code& code = Code::Handle(); | 1491 Code& code = Code::Handle(); |
1469 for (intptr_t frame_index = 0; frame_index < sample->length(); | 1492 for (intptr_t frame_index = 0; frame_index < sample->length(); |
1470 frame_index++) { | 1493 frame_index++) { |
1471 ASSERT(sample->At(frame_index) != 0); | 1494 ASSERT(sample->At(frame_index) != 0); |
1472 intptr_t index = | 1495 intptr_t index = |
1473 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); | 1496 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); |
1474 ASSERT(index >= 0); | 1497 ASSERT(index >= 0); |
1475 ProfileCode* profile_code = | 1498 ProfileCode* profile_code = |
1476 GetProfileCode(sample->At(frame_index), sample->timestamp()); | 1499 GetProfileCode(sample->At(frame_index), sample->timestamp()); |
1477 ASSERT(profile_code->code_table_index() == index); | 1500 ASSERT(profile_code->code_table_index() == index); |
1478 code ^= profile_code->code(); | 1501 code ^= profile_code->code(); |
1479 current = current->GetChild(index); | 1502 current = current->GetChild(index); |
1480 if (ShouldTickNode(sample, frame_index)) { | 1503 if (ShouldTickNode(sample, frame_index)) { |
1481 current->Tick(); | 1504 current->Tick(sample, (frame_index == 0)); |
1482 } | 1505 } |
1483 current = AppendKind(code, current); | 1506 current = AppendKind(code, current, sample); |
1484 } | 1507 } |
1485 // Truncated tag. | 1508 // Truncated tag. |
1486 if (sample->truncated()) { | 1509 if (sample->truncated()) { |
1487 current = AppendTruncatedTag(current); | 1510 current = AppendTruncatedTag(current, sample); |
1488 } | 1511 } |
1489 } | 1512 } |
1490 } | 1513 } |
1491 | 1514 |
1492 void BuildFunctionTrie(Profile::TrieKind kind) { | 1515 void BuildFunctionTrie(Profile::TrieKind kind) { |
1493 ProfileFunctionTrieNode* root = new ProfileFunctionTrieNode( | 1516 ProfileFunctionTrieNode* root = new ProfileFunctionTrieNode( |
1494 GetProfileFunctionTagIndex(VMTag::kRootTagId)); | 1517 GetProfileFunctionTagIndex(VMTag::kRootTagId)); |
1495 // We tick the functions while building the trie, but, we don't want to do | 1518 // We tick the functions while building the trie, but, we don't want to do |
1496 // it for both tries, just the exclusive trie. | 1519 // it for both tries, just the exclusive trie. |
1497 inclusive_tree_ = IsInclusiveTrie(kind); | 1520 inclusive_tree_ = IsInclusiveTrie(kind); |
(...skipping 10 matching lines...) Expand all Loading... | |
1508 void BuildInclusiveFunctionTrie(ProfileFunctionTrieNode* root) { | 1531 void BuildInclusiveFunctionTrie(ProfileFunctionTrieNode* root) { |
1509 ScopeTimer sw("ProfileBuilder::BuildInclusiveFunctionTrie", | 1532 ScopeTimer sw("ProfileBuilder::BuildInclusiveFunctionTrie", |
1510 FLAG_trace_profiler); | 1533 FLAG_trace_profiler); |
1511 ASSERT(!tick_functions_); | 1534 ASSERT(!tick_functions_); |
1512 for (intptr_t sample_index = 0; sample_index < samples_->length(); | 1535 for (intptr_t sample_index = 0; sample_index < samples_->length(); |
1513 sample_index++) { | 1536 sample_index++) { |
1514 ProcessedSample* sample = samples_->At(sample_index); | 1537 ProcessedSample* sample = samples_->At(sample_index); |
1515 | 1538 |
1516 // Tick the root. | 1539 // Tick the root. |
1517 ProfileFunctionTrieNode* current = root; | 1540 ProfileFunctionTrieNode* current = root; |
1518 current->Tick(); | 1541 current->Tick(sample); |
1519 | |
1520 // VM & User tags. | 1542 // VM & User tags. |
1521 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); | 1543 current = |
1544 AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); | |
1522 | 1545 |
1523 // Truncated tag. | 1546 // Truncated tag. |
1524 if (sample->truncated()) { | 1547 if (sample->truncated()) { |
1525 current = AppendTruncatedTag(current); | 1548 current = AppendTruncatedTag(current, sample); |
1526 } | 1549 } |
1527 | 1550 |
1528 // Walk the sampled PCs. | 1551 // Walk the sampled PCs. |
1529 for (intptr_t frame_index = sample->length() - 1; frame_index >= 0; | 1552 for (intptr_t frame_index = sample->length() - 1; frame_index >= 0; |
1530 frame_index--) { | 1553 frame_index--) { |
1531 ASSERT(sample->At(frame_index) != 0); | 1554 ASSERT(sample->At(frame_index) != 0); |
1532 current = ProcessFrame(current, sample_index, sample, frame_index); | 1555 current = ProcessFrame(current, sample_index, sample, frame_index); |
1533 } | 1556 } |
1534 | 1557 |
1535 if (!sample->first_frame_executing()) { | 1558 if (!sample->first_frame_executing()) { |
1536 current = AppendExitFrame(sample->vm_tag(), current); | 1559 current = AppendExitFrame(sample->vm_tag(), current, sample); |
1537 } | 1560 } |
1538 | 1561 |
1539 sample->set_timeline_trie(current); | 1562 sample->set_timeline_trie(current); |
1540 } | 1563 } |
1541 } | 1564 } |
1542 | 1565 |
1543 void BuildExclusiveFunctionTrie(ProfileFunctionTrieNode* root) { | 1566 void BuildExclusiveFunctionTrie(ProfileFunctionTrieNode* root) { |
1544 ScopeTimer sw("ProfileBuilder::BuildExclusiveFunctionTrie", | 1567 ScopeTimer sw("ProfileBuilder::BuildExclusiveFunctionTrie", |
1545 FLAG_trace_profiler); | 1568 FLAG_trace_profiler); |
1546 ASSERT(tick_functions_); | 1569 ASSERT(tick_functions_); |
1547 for (intptr_t sample_index = 0; sample_index < samples_->length(); | 1570 for (intptr_t sample_index = 0; sample_index < samples_->length(); |
1548 sample_index++) { | 1571 sample_index++) { |
1549 ProcessedSample* sample = samples_->At(sample_index); | 1572 ProcessedSample* sample = samples_->At(sample_index); |
1550 | 1573 |
1551 // Tick the root. | 1574 // Tick the root. |
1552 ProfileFunctionTrieNode* current = root; | 1575 ProfileFunctionTrieNode* current = root; |
1553 current->Tick(); | 1576 current->Tick(sample); |
1554 | |
1555 // VM & User tags. | 1577 // VM & User tags. |
1556 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); | 1578 current = |
1579 AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); | |
1557 | 1580 |
1558 ResetKind(); | 1581 ResetKind(); |
1559 | 1582 |
1560 if (!sample->first_frame_executing()) { | 1583 if (!sample->first_frame_executing()) { |
1561 current = AppendExitFrame(sample->vm_tag(), current); | 1584 current = AppendExitFrame(sample->vm_tag(), current, sample); |
1562 } | 1585 } |
1563 | 1586 |
1564 // Walk the sampled PCs. | 1587 // Walk the sampled PCs. |
1565 for (intptr_t frame_index = 0; frame_index < sample->length(); | 1588 for (intptr_t frame_index = 0; frame_index < sample->length(); |
1566 frame_index++) { | 1589 frame_index++) { |
1567 ASSERT(sample->At(frame_index) != 0); | 1590 ASSERT(sample->At(frame_index) != 0); |
1568 current = ProcessFrame(current, sample_index, sample, frame_index); | 1591 current = ProcessFrame(current, sample_index, sample, frame_index); |
1569 } | 1592 } |
1570 | 1593 |
1571 TickExitFrameFunction(sample->vm_tag(), sample_index); | 1594 TickExitFrameFunction(sample->vm_tag(), sample_index, sample); |
1572 | 1595 |
1573 // Truncated tag. | 1596 // Truncated tag. |
1574 if (sample->truncated()) { | 1597 if (sample->truncated()) { |
1575 current = AppendTruncatedTag(current); | 1598 current = AppendTruncatedTag(current, sample); |
1576 InclusiveTickTruncatedTag(); | 1599 InclusiveTickTruncatedTag(sample); |
1577 } | 1600 } |
1578 } | 1601 } |
1579 } | 1602 } |
1580 | 1603 |
1581 ProfileFunctionTrieNode* ProcessFrame(ProfileFunctionTrieNode* current, | 1604 ProfileFunctionTrieNode* ProcessFrame(ProfileFunctionTrieNode* current, |
1582 intptr_t sample_index, | 1605 intptr_t sample_index, |
1583 ProcessedSample* sample, | 1606 ProcessedSample* sample, |
1584 intptr_t frame_index) { | 1607 intptr_t frame_index) { |
1585 const uword pc = sample->At(frame_index); | 1608 const uword pc = sample->At(frame_index); |
1586 ProfileCode* profile_code = GetProfileCode(pc, sample->timestamp()); | 1609 ProfileCode* profile_code = GetProfileCode(pc, sample->timestamp()); |
(...skipping 17 matching lines...) Expand all Loading... | |
1604 name.ToCString(), | 1627 name.ToCString(), |
1605 (*inlined_token_positions)[i].ToCString()); | 1628 (*inlined_token_positions)[i].ToCString()); |
1606 } | 1629 } |
1607 } | 1630 } |
1608 } | 1631 } |
1609 | 1632 |
1610 if (code.IsNull() || (inlined_functions == NULL) || | 1633 if (code.IsNull() || (inlined_functions == NULL) || |
1611 (inlined_functions->length() <= 1)) { | 1634 (inlined_functions->length() <= 1)) { |
1612 // No inlined functions. | 1635 // No inlined functions. |
1613 if (inclusive_tree_) { | 1636 if (inclusive_tree_) { |
1614 current = AppendKind(code, current); | 1637 current = AppendKind(code, current, sample); |
1615 } | 1638 } |
1616 current = ProcessFunction(current, sample_index, sample, frame_index, | 1639 current = ProcessFunction(current, sample_index, sample, frame_index, |
1617 function, token_position, code_index); | 1640 function, token_position, code_index); |
1618 if (!inclusive_tree_) { | 1641 if (!inclusive_tree_) { |
1619 current = AppendKind(code, current); | 1642 current = AppendKind(code, current, sample); |
1620 } | 1643 } |
1621 return current; | 1644 return current; |
1622 } | 1645 } |
1623 | 1646 |
1647 // TODO(bkonyi) deal with this | |
1624 ASSERT(code.is_optimized()); | 1648 ASSERT(code.is_optimized()); |
1625 | 1649 |
1626 if (inclusive_tree_) { | 1650 if (inclusive_tree_) { |
1627 for (intptr_t i = 0; i < inlined_functions->length(); i++) { | 1651 for (intptr_t i = 0; i < inlined_functions->length(); i++) { |
1628 const Function* inlined_function = (*inlined_functions)[i]; | 1652 const Function* inlined_function = (*inlined_functions)[i]; |
1629 ASSERT(inlined_function != NULL); | 1653 ASSERT(inlined_function != NULL); |
1630 ASSERT(!inlined_function->IsNull()); | 1654 ASSERT(!inlined_function->IsNull()); |
1631 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; | 1655 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; |
1632 const bool inliner = i == 0; | 1656 const bool inliner = i == 0; |
1633 if (inliner) { | 1657 if (inliner) { |
1634 current = AppendKind(code, current); | 1658 current = AppendKind(code, current, sample); |
1635 } | 1659 } |
1636 current = ProcessInlinedFunction(current, sample_index, sample, | 1660 current = ProcessInlinedFunction(current, sample_index, sample, |
1637 frame_index, inlined_function, | 1661 frame_index, inlined_function, |
1638 inlined_token_position, code_index); | 1662 inlined_token_position, code_index); |
1639 if (inliner) { | 1663 if (inliner) { |
1640 current = AppendKind(kInlineStart, current); | 1664 current = AppendKind(kInlineStart, current, sample); |
1641 } | 1665 } |
1642 } | 1666 } |
1643 current = AppendKind(kInlineFinish, current); | 1667 current = AppendKind(kInlineFinish, current, sample); |
1644 } else { | 1668 } else { |
1645 // Append the inlined children. | 1669 // Append the inlined children. |
1646 current = AppendKind(kInlineFinish, current); | 1670 current = AppendKind(kInlineFinish, current, sample); |
1647 for (intptr_t i = inlined_functions->length() - 1; i >= 0; i--) { | 1671 for (intptr_t i = inlined_functions->length() - 1; i >= 0; i--) { |
1648 const Function* inlined_function = (*inlined_functions)[i]; | 1672 const Function* inlined_function = (*inlined_functions)[i]; |
1649 ASSERT(inlined_function != NULL); | 1673 ASSERT(inlined_function != NULL); |
1650 ASSERT(!inlined_function->IsNull()); | 1674 ASSERT(!inlined_function->IsNull()); |
1651 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; | 1675 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; |
1652 const bool inliner = i == 0; | 1676 const bool inliner = i == 0; |
1653 if (inliner) { | 1677 if (inliner) { |
1654 current = AppendKind(kInlineStart, current); | 1678 current = AppendKind(kInlineStart, current, sample); |
1655 } | 1679 } |
1656 current = ProcessInlinedFunction(current, sample_index, sample, | 1680 current = ProcessInlinedFunction(current, sample_index, sample, |
1657 frame_index + i, inlined_function, | 1681 frame_index + i, inlined_function, |
1658 inlined_token_position, code_index); | 1682 inlined_token_position, code_index); |
1659 if (inliner) { | 1683 if (inliner) { |
1660 current = AppendKind(code, current); | 1684 current = AppendKind(code, current, sample); |
1661 } | 1685 } |
1662 } | 1686 } |
1663 } | 1687 } |
1664 | 1688 |
1665 return current; | 1689 return current; |
1666 } | 1690 } |
1667 | 1691 |
1668 ProfileFunctionTrieNode* ProcessInlinedFunction( | 1692 ProfileFunctionTrieNode* ProcessInlinedFunction( |
1669 ProfileFunctionTrieNode* current, | 1693 ProfileFunctionTrieNode* current, |
1670 intptr_t sample_index, | 1694 intptr_t sample_index, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1705 THR_Print("S[%" Pd "]F[%" Pd "] %s %s 0x%" Px "\n", sample_index, | 1729 THR_Print("S[%" Pd "]F[%" Pd "] %s %s 0x%" Px "\n", sample_index, |
1706 frame_index, function->Name(), token_position.ToCString(), | 1730 frame_index, function->Name(), token_position.ToCString(), |
1707 sample->At(frame_index)); | 1731 sample->At(frame_index)); |
1708 } | 1732 } |
1709 function->Tick(IsExecutingFrame(sample, frame_index), sample_index, | 1733 function->Tick(IsExecutingFrame(sample, frame_index), sample_index, |
1710 token_position); | 1734 token_position); |
1711 } | 1735 } |
1712 function->AddProfileCode(code_index); | 1736 function->AddProfileCode(code_index); |
1713 current = current->GetChild(function->table_index()); | 1737 current = current->GetChild(function->table_index()); |
1714 if (ShouldTickNode(sample, frame_index)) { | 1738 if (ShouldTickNode(sample, frame_index)) { |
1715 current->Tick(); | 1739 current->Tick(sample, (frame_index == 0)); |
1716 } | 1740 } |
1717 current->AddCodeObjectIndex(code_index); | 1741 current->AddCodeObjectIndex(code_index); |
1718 return current; | 1742 return current; |
1719 } | 1743 } |
1720 | 1744 |
1721 // Tick the truncated tag's inclusive tick count. | 1745 // Tick the truncated tag's inclusive tick count. |
1722 void InclusiveTickTruncatedTag() { | 1746 void InclusiveTickTruncatedTag(ProcessedSample* sample) { |
1723 ProfileCodeTable* tag_table = profile_->tag_code_; | 1747 ProfileCodeTable* tag_table = profile_->tag_code_; |
1724 intptr_t index = tag_table->FindCodeIndexForPC(VMTag::kTruncatedTagId); | 1748 intptr_t index = tag_table->FindCodeIndexForPC(VMTag::kTruncatedTagId); |
1725 ASSERT(index >= 0); | 1749 ASSERT(index >= 0); |
1726 ProfileCode* code = tag_table->At(index); | 1750 ProfileCode* code = tag_table->At(index); |
1727 code->IncInclusiveTicks(); | 1751 code->IncInclusiveTicks(); |
1728 ASSERT(code != NULL); | 1752 ASSERT(code != NULL); |
1729 ProfileFunction* function = code->function(); | 1753 ProfileFunction* function = code->function(); |
1730 function->IncInclusiveTicks(); | 1754 function->IncInclusiveTicks(); |
1731 } | 1755 } |
1732 | 1756 |
1733 | 1757 |
1734 // Tag append functions are overloaded for |ProfileCodeTrieNode| and | 1758 // Tag append functions are overloaded for |ProfileCodeTrieNode| and |
1735 // |ProfileFunctionTrieNode| types. | 1759 // |ProfileFunctionTrieNode| types. |
1736 | 1760 |
1737 // ProfileCodeTrieNode | 1761 // ProfileCodeTrieNode |
1738 ProfileCodeTrieNode* AppendUserTag(uword user_tag, | 1762 ProfileCodeTrieNode* AppendUserTag(uword user_tag, |
1739 ProfileCodeTrieNode* current) { | 1763 ProfileCodeTrieNode* current, |
1764 ProcessedSample* sample) { | |
1740 intptr_t user_tag_index = GetProfileCodeTagIndex(user_tag); | 1765 intptr_t user_tag_index = GetProfileCodeTagIndex(user_tag); |
1741 if (user_tag_index >= 0) { | 1766 if (user_tag_index >= 0) { |
1742 current = current->GetChild(user_tag_index); | 1767 current = current->GetChild(user_tag_index); |
1743 current->Tick(); | 1768 current->Tick(sample); |
1744 } | 1769 } |
1745 return current; | 1770 return current; |
1746 } | 1771 } |
1747 | 1772 |
1748 ProfileCodeTrieNode* AppendTruncatedTag(ProfileCodeTrieNode* current) { | 1773 ProfileCodeTrieNode* AppendTruncatedTag(ProfileCodeTrieNode* current, |
1774 ProcessedSample* sample) { | |
1749 intptr_t truncated_tag_index = | 1775 intptr_t truncated_tag_index = |
1750 GetProfileCodeTagIndex(VMTag::kTruncatedTagId); | 1776 GetProfileCodeTagIndex(VMTag::kTruncatedTagId); |
1751 ASSERT(truncated_tag_index >= 0); | 1777 ASSERT(truncated_tag_index >= 0); |
1752 current = current->GetChild(truncated_tag_index); | 1778 current = current->GetChild(truncated_tag_index); |
1753 current->Tick(); | 1779 current->Tick(sample); |
1754 return current; | 1780 return current; |
1755 } | 1781 } |
1756 | 1782 |
1757 ProfileCodeTrieNode* AppendVMTag(uword vm_tag, ProfileCodeTrieNode* current) { | 1783 ProfileCodeTrieNode* AppendVMTag(uword vm_tag, |
1784 ProfileCodeTrieNode* current, | |
1785 ProcessedSample* sample) { | |
1758 if (VMTag::IsNativeEntryTag(vm_tag)) { | 1786 if (VMTag::IsNativeEntryTag(vm_tag)) { |
1759 // Insert a dummy kNativeTagId node. | 1787 // Insert a dummy kNativeTagId node. |
1760 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kNativeTagId); | 1788 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kNativeTagId); |
1761 current = current->GetChild(tag_index); | 1789 current = current->GetChild(tag_index); |
1762 // Give the tag a tick. | 1790 // Give the tag a tick. |
1763 current->Tick(); | 1791 current->Tick(sample); |
1764 } else if (VMTag::IsRuntimeEntryTag(vm_tag)) { | 1792 } else if (VMTag::IsRuntimeEntryTag(vm_tag)) { |
1765 // Insert a dummy kRuntimeTagId node. | 1793 // Insert a dummy kRuntimeTagId node. |
1766 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kRuntimeTagId); | 1794 intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kRuntimeTagId); |
1767 current = current->GetChild(tag_index); | 1795 current = current->GetChild(tag_index); |
1768 // Give the tag a tick. | 1796 // Give the tag a tick. |
1769 current->Tick(); | 1797 current->Tick(sample); |
1770 } else { | 1798 } else { |
1771 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); | 1799 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); |
1772 current = current->GetChild(tag_index); | 1800 current = current->GetChild(tag_index); |
1773 // Give the tag a tick. | 1801 // Give the tag a tick. |
1774 current->Tick(); | 1802 current->Tick(sample); |
1775 } | 1803 } |
1776 return current; | 1804 return current; |
1777 } | 1805 } |
1778 | 1806 |
1779 ProfileCodeTrieNode* AppendSpecificNativeRuntimeEntryVMTag( | 1807 ProfileCodeTrieNode* AppendSpecificNativeRuntimeEntryVMTag( |
1780 uword vm_tag, | 1808 uword vm_tag, |
1781 ProfileCodeTrieNode* current) { | 1809 ProfileCodeTrieNode* current, |
1810 ProcessedSample* sample) { | |
1782 // Only Native and Runtime entries have a second VM tag. | 1811 // Only Native and Runtime entries have a second VM tag. |
1783 if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) { | 1812 if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) { |
1784 return current; | 1813 return current; |
1785 } | 1814 } |
1786 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); | 1815 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); |
1787 current = current->GetChild(tag_index); | 1816 current = current->GetChild(tag_index); |
1788 // Give the tag a tick. | 1817 // Give the tag a tick. |
1789 current->Tick(); | 1818 current->Tick(sample); |
1790 return current; | 1819 return current; |
1791 } | 1820 } |
1792 | 1821 |
1793 uword ProfileInfoKindToVMTag(ProfileInfoKind kind) { | 1822 uword ProfileInfoKindToVMTag(ProfileInfoKind kind) { |
1794 switch (kind) { | 1823 switch (kind) { |
1795 case kNone: | 1824 case kNone: |
1796 return VMTag::kNoneCodeTagId; | 1825 return VMTag::kNoneCodeTagId; |
1797 case kOptimized: | 1826 case kOptimized: |
1798 return VMTag::kOptimizedCodeTagId; | 1827 return VMTag::kOptimizedCodeTagId; |
1799 case kUnoptimized: | 1828 case kUnoptimized: |
1800 return VMTag::kUnoptimizedCodeTagId; | 1829 return VMTag::kUnoptimizedCodeTagId; |
1801 case kNative: | 1830 case kNative: |
1802 return VMTag::kNativeCodeTagId; | 1831 return VMTag::kNativeCodeTagId; |
1803 case kInlineStart: | 1832 case kInlineStart: |
1804 return VMTag::kInlineStartCodeTagId; | 1833 return VMTag::kInlineStartCodeTagId; |
1805 case kInlineFinish: | 1834 case kInlineFinish: |
1806 return VMTag::kInlineEndCodeTagId; | 1835 return VMTag::kInlineEndCodeTagId; |
1807 default: | 1836 default: |
1808 UNIMPLEMENTED(); | 1837 UNIMPLEMENTED(); |
1809 return VMTag::kInvalidTagId; | 1838 return VMTag::kInvalidTagId; |
1810 } | 1839 } |
1811 } | 1840 } |
1812 | 1841 |
1813 ProfileCodeTrieNode* AppendKind(ProfileInfoKind kind, | 1842 ProfileCodeTrieNode* AppendKind(ProfileInfoKind kind, |
1814 ProfileCodeTrieNode* current) { | 1843 ProfileCodeTrieNode* current, |
1844 ProcessedSample* sample) { | |
1815 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { | 1845 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { |
1816 // Only emit if debug tags are requested. | 1846 // Only emit if debug tags are requested. |
1817 return current; | 1847 return current; |
1818 } | 1848 } |
1819 if (kind != info_kind_) { | 1849 if (kind != info_kind_) { |
1820 info_kind_ = kind; | 1850 info_kind_ = kind; |
1821 intptr_t tag_index = GetProfileCodeTagIndex(ProfileInfoKindToVMTag(kind)); | 1851 intptr_t tag_index = GetProfileCodeTagIndex(ProfileInfoKindToVMTag(kind)); |
1822 ASSERT(tag_index >= 0); | 1852 ASSERT(tag_index >= 0); |
1823 current = current->GetChild(tag_index); | 1853 current = current->GetChild(tag_index); |
1824 current->Tick(); | 1854 current->Tick(sample); |
1825 } | 1855 } |
1826 return current; | 1856 return current; |
1827 } | 1857 } |
1828 | 1858 |
1829 ProfileCodeTrieNode* AppendKind(const Code& code, | 1859 ProfileCodeTrieNode* AppendKind(const Code& code, |
1830 ProfileCodeTrieNode* current) { | 1860 ProfileCodeTrieNode* current, |
1861 ProcessedSample* sample) { | |
1831 if (code.IsNull()) { | 1862 if (code.IsNull()) { |
1832 return AppendKind(kNone, current); | 1863 return AppendKind(kNone, current, sample); |
1833 } else if (code.is_optimized()) { | 1864 } else if (code.is_optimized()) { |
1834 return AppendKind(kOptimized, current); | 1865 return AppendKind(kOptimized, current, sample); |
1835 } else { | 1866 } else { |
1836 return AppendKind(kUnoptimized, current); | 1867 return AppendKind(kUnoptimized, current, sample); |
1837 } | 1868 } |
1838 } | 1869 } |
1839 | 1870 |
1840 ProfileCodeTrieNode* AppendVMTags(uword vm_tag, | 1871 ProfileCodeTrieNode* AppendVMTags(uword vm_tag, |
1841 ProfileCodeTrieNode* current) { | 1872 ProfileCodeTrieNode* current, |
1842 current = AppendVMTag(vm_tag, current); | 1873 ProcessedSample* sample) { |
1843 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); | 1874 current = AppendVMTag(vm_tag, current, sample); |
1875 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); | |
1844 return current; | 1876 return current; |
1845 } | 1877 } |
1846 | 1878 |
1847 void TickExitFrame(uword vm_tag, intptr_t serial) { | 1879 void TickExitFrame(uword vm_tag, intptr_t serial, ProcessedSample* sample) { |
1848 if (FLAG_profile_vm) { | 1880 if (FLAG_profile_vm) { |
1849 return; | 1881 return; |
1850 } | 1882 } |
1851 if (!VMTag::IsExitFrameTag(vm_tag)) { | 1883 if (!VMTag::IsExitFrameTag(vm_tag)) { |
1852 return; | 1884 return; |
1853 } | 1885 } |
1854 ProfileCodeTable* tag_table = profile_->tag_code_; | 1886 ProfileCodeTable* tag_table = profile_->tag_code_; |
1855 ProfileCode* code = tag_table->FindCodeForPC(vm_tag); | 1887 ProfileCode* code = tag_table->FindCodeForPC(vm_tag); |
1856 ASSERT(code != NULL); | 1888 ASSERT(code != NULL); |
1857 code->Tick(vm_tag, true, serial); | 1889 code->Tick(vm_tag, true, serial); |
1858 } | 1890 } |
1859 | 1891 |
1860 void TickExitFrameFunction(uword vm_tag, intptr_t serial) { | 1892 void TickExitFrameFunction(uword vm_tag, |
1893 intptr_t serial, | |
1894 ProcessedSample* sample) { | |
Cutch
2017/03/21 20:27:11
sample doesn't appear used here?
bkonyi
2017/03/22 21:25:21
Removed.
| |
1861 if (FLAG_profile_vm) { | 1895 if (FLAG_profile_vm) { |
1862 return; | 1896 return; |
1863 } | 1897 } |
1864 if (!VMTag::IsExitFrameTag(vm_tag)) { | 1898 if (!VMTag::IsExitFrameTag(vm_tag)) { |
1865 return; | 1899 return; |
1866 } | 1900 } |
1867 ProfileCodeTable* tag_table = profile_->tag_code_; | 1901 ProfileCodeTable* tag_table = profile_->tag_code_; |
1868 ProfileCode* code = tag_table->FindCodeForPC(vm_tag); | 1902 ProfileCode* code = tag_table->FindCodeForPC(vm_tag); |
1869 ASSERT(code != NULL); | 1903 ASSERT(code != NULL); |
1870 ProfileFunction* function = code->function(); | 1904 ProfileFunction* function = code->function(); |
1871 ASSERT(function != NULL); | 1905 ASSERT(function != NULL); |
1872 function->Tick(true, serial, TokenPosition::kNoSource); | 1906 function->Tick(true, serial, TokenPosition::kNoSource); |
1873 } | 1907 } |
1874 | 1908 |
1875 ProfileCodeTrieNode* AppendExitFrame(uword vm_tag, | 1909 ProfileCodeTrieNode* AppendExitFrame(uword vm_tag, |
1876 ProfileCodeTrieNode* current) { | 1910 ProfileCodeTrieNode* current, |
1911 ProcessedSample* sample) { | |
1877 if (FLAG_profile_vm) { | 1912 if (FLAG_profile_vm) { |
1878 return current; | 1913 return current; |
1879 } | 1914 } |
1880 | 1915 |
1881 if (!VMTag::IsExitFrameTag(vm_tag)) { | 1916 if (!VMTag::IsExitFrameTag(vm_tag)) { |
1882 return current; | 1917 return current; |
1883 } | 1918 } |
1884 | 1919 |
1885 if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) { | 1920 if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) { |
1886 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); | 1921 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); |
1887 } else { | 1922 } else { |
1888 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); | 1923 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); |
1889 current = current->GetChild(tag_index); | 1924 current = current->GetChild(tag_index); |
1890 // Give the tag a tick. | 1925 // Give the tag a tick. |
1891 current->Tick(); | 1926 current->Tick(sample); |
1892 } | 1927 } |
1893 return current; | 1928 return current; |
1894 } | 1929 } |
1895 | 1930 |
1896 ProfileCodeTrieNode* AppendTags(uword vm_tag, | 1931 ProfileCodeTrieNode* AppendTags(uword vm_tag, |
1897 uword user_tag, | 1932 uword user_tag, |
1898 ProfileCodeTrieNode* current) { | 1933 ProfileCodeTrieNode* current, |
1934 ProcessedSample* sample) { | |
1899 if (FLAG_profile_vm) { | 1935 if (FLAG_profile_vm) { |
1900 // None. | 1936 // None. |
1901 if (tag_order() == Profile::kNoTags) { | 1937 if (tag_order() == Profile::kNoTags) { |
1902 return current; | 1938 return current; |
1903 } | 1939 } |
1904 // User first. | 1940 // User first. |
1905 if ((tag_order() == Profile::kUserVM) || | 1941 if ((tag_order() == Profile::kUserVM) || |
1906 (tag_order() == Profile::kUser)) { | 1942 (tag_order() == Profile::kUser)) { |
1907 current = AppendUserTag(user_tag, current); | 1943 current = AppendUserTag(user_tag, current, sample); |
1908 // Only user. | 1944 // Only user. |
1909 if (tag_order() == Profile::kUser) { | 1945 if (tag_order() == Profile::kUser) { |
1910 return current; | 1946 return current; |
1911 } | 1947 } |
1912 return AppendVMTags(vm_tag, current); | 1948 return AppendVMTags(vm_tag, current, sample); |
1913 } | 1949 } |
1914 // VM first. | 1950 // VM first. |
1915 ASSERT((tag_order() == Profile::kVMUser) || | 1951 ASSERT((tag_order() == Profile::kVMUser) || |
1916 (tag_order() == Profile::kVM)); | 1952 (tag_order() == Profile::kVM)); |
1917 current = AppendVMTags(vm_tag, current); | 1953 current = AppendVMTags(vm_tag, current, sample); |
1918 // Only VM. | 1954 // Only VM. |
1919 if (tag_order() == Profile::kVM) { | 1955 if (tag_order() == Profile::kVM) { |
1920 return current; | 1956 return current; |
1921 } | 1957 } |
1922 return AppendUserTag(user_tag, current); | 1958 return AppendUserTag(user_tag, current, sample); |
1923 } | 1959 } |
1924 | 1960 |
1925 if (tag_order() == Profile::kNoTags) { | 1961 if (tag_order() == Profile::kNoTags) { |
1926 return current; | 1962 return current; |
1927 } | 1963 } |
1928 | 1964 |
1929 return AppendUserTag(user_tag, current); | 1965 return AppendUserTag(user_tag, current, sample); |
1930 } | 1966 } |
1931 | 1967 |
1932 // ProfileFunctionTrieNode | 1968 // ProfileFunctionTrieNode |
1933 void ResetKind() { info_kind_ = kNone; } | 1969 void ResetKind() { info_kind_ = kNone; } |
1934 | 1970 |
1935 ProfileFunctionTrieNode* AppendKind(ProfileInfoKind kind, | 1971 ProfileFunctionTrieNode* AppendKind(ProfileInfoKind kind, |
1936 ProfileFunctionTrieNode* current) { | 1972 ProfileFunctionTrieNode* current, |
1973 ProcessedSample* sample) { | |
1937 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { | 1974 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { |
1938 // Only emit if debug tags are requested. | 1975 // Only emit if debug tags are requested. |
1939 return current; | 1976 return current; |
1940 } | 1977 } |
1941 if (kind != info_kind_) { | 1978 if (kind != info_kind_) { |
1942 info_kind_ = kind; | 1979 info_kind_ = kind; |
1943 intptr_t tag_index = | 1980 intptr_t tag_index = |
1944 GetProfileFunctionTagIndex(ProfileInfoKindToVMTag(kind)); | 1981 GetProfileFunctionTagIndex(ProfileInfoKindToVMTag(kind)); |
1945 ASSERT(tag_index >= 0); | 1982 ASSERT(tag_index >= 0); |
1946 current = current->GetChild(tag_index); | 1983 current = current->GetChild(tag_index); |
1947 current->Tick(); | 1984 current->Tick(sample); |
1948 } | 1985 } |
1949 return current; | 1986 return current; |
1950 } | 1987 } |
1951 | 1988 |
1952 ProfileFunctionTrieNode* AppendKind(const Code& code, | 1989 ProfileFunctionTrieNode* AppendKind(const Code& code, |
1953 ProfileFunctionTrieNode* current) { | 1990 ProfileFunctionTrieNode* current, |
1991 ProcessedSample* sample) { | |
1954 if (code.IsNull()) { | 1992 if (code.IsNull()) { |
1955 return AppendKind(kNone, current); | 1993 return AppendKind(kNone, current, sample); |
1956 } else if (code.is_optimized()) { | 1994 } else if (code.is_optimized()) { |
1957 return AppendKind(kOptimized, current); | 1995 return AppendKind(kOptimized, current, sample); |
1958 } else { | 1996 } else { |
1959 return AppendKind(kUnoptimized, current); | 1997 return AppendKind(kUnoptimized, current, sample); |
1960 } | 1998 } |
1961 } | 1999 } |
1962 | 2000 |
1963 ProfileFunctionTrieNode* AppendUserTag(uword user_tag, | 2001 ProfileFunctionTrieNode* AppendUserTag(uword user_tag, |
1964 ProfileFunctionTrieNode* current) { | 2002 ProfileFunctionTrieNode* current, |
2003 ProcessedSample* sample) { | |
1965 intptr_t user_tag_index = GetProfileFunctionTagIndex(user_tag); | 2004 intptr_t user_tag_index = GetProfileFunctionTagIndex(user_tag); |
1966 if (user_tag_index >= 0) { | 2005 if (user_tag_index >= 0) { |
1967 current = current->GetChild(user_tag_index); | 2006 current = current->GetChild(user_tag_index); |
1968 current->Tick(); | 2007 current->Tick(sample); |
1969 } | 2008 } |
1970 return current; | 2009 return current; |
1971 } | 2010 } |
1972 | 2011 |
1973 ProfileFunctionTrieNode* AppendTruncatedTag( | 2012 ProfileFunctionTrieNode* AppendTruncatedTag(ProfileFunctionTrieNode* current, |
1974 ProfileFunctionTrieNode* current) { | 2013 ProcessedSample* sample) { |
1975 intptr_t truncated_tag_index = | 2014 intptr_t truncated_tag_index = |
1976 GetProfileFunctionTagIndex(VMTag::kTruncatedTagId); | 2015 GetProfileFunctionTagIndex(VMTag::kTruncatedTagId); |
1977 ASSERT(truncated_tag_index >= 0); | 2016 ASSERT(truncated_tag_index >= 0); |
1978 current = current->GetChild(truncated_tag_index); | 2017 current = current->GetChild(truncated_tag_index); |
1979 current->Tick(); | 2018 current->Tick(sample); |
1980 return current; | 2019 return current; |
1981 } | 2020 } |
1982 | 2021 |
1983 ProfileFunctionTrieNode* AppendVMTag(uword vm_tag, | 2022 ProfileFunctionTrieNode* AppendVMTag(uword vm_tag, |
1984 ProfileFunctionTrieNode* current) { | 2023 ProfileFunctionTrieNode* current, |
2024 ProcessedSample* sample) { | |
1985 if (VMTag::IsNativeEntryTag(vm_tag)) { | 2025 if (VMTag::IsNativeEntryTag(vm_tag)) { |
1986 // Insert a dummy kNativeTagId node. | 2026 // Insert a dummy kNativeTagId node. |
1987 intptr_t tag_index = GetProfileFunctionTagIndex(VMTag::kNativeTagId); | 2027 intptr_t tag_index = GetProfileFunctionTagIndex(VMTag::kNativeTagId); |
1988 current = current->GetChild(tag_index); | 2028 current = current->GetChild(tag_index); |
1989 // Give the tag a tick. | 2029 // Give the tag a tick. |
1990 current->Tick(); | 2030 current->Tick(sample); |
1991 } else if (VMTag::IsRuntimeEntryTag(vm_tag)) { | 2031 } else if (VMTag::IsRuntimeEntryTag(vm_tag)) { |
1992 // Insert a dummy kRuntimeTagId node. | 2032 // Insert a dummy kRuntimeTagId node. |
1993 intptr_t tag_index = GetProfileFunctionTagIndex(VMTag::kRuntimeTagId); | 2033 intptr_t tag_index = GetProfileFunctionTagIndex(VMTag::kRuntimeTagId); |
1994 current = current->GetChild(tag_index); | 2034 current = current->GetChild(tag_index); |
1995 // Give the tag a tick. | 2035 // Give the tag a tick. |
1996 current->Tick(); | 2036 current->Tick(sample); |
1997 } else { | 2037 } else { |
1998 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); | 2038 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); |
1999 current = current->GetChild(tag_index); | 2039 current = current->GetChild(tag_index); |
2000 // Give the tag a tick. | 2040 // Give the tag a tick. |
2001 current->Tick(); | 2041 current->Tick(sample); |
2002 } | 2042 } |
2003 return current; | 2043 return current; |
2004 } | 2044 } |
2005 | 2045 |
2006 ProfileFunctionTrieNode* AppendSpecificNativeRuntimeEntryVMTag( | 2046 ProfileFunctionTrieNode* AppendSpecificNativeRuntimeEntryVMTag( |
2007 uword vm_tag, | 2047 uword vm_tag, |
2008 ProfileFunctionTrieNode* current) { | 2048 ProfileFunctionTrieNode* current, |
2049 ProcessedSample* sample) { | |
2009 // Only Native and Runtime entries have a second VM tag. | 2050 // Only Native and Runtime entries have a second VM tag. |
2010 if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) { | 2051 if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) { |
2011 return current; | 2052 return current; |
2012 } | 2053 } |
2013 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); | 2054 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); |
2014 current = current->GetChild(tag_index); | 2055 current = current->GetChild(tag_index); |
2015 // Give the tag a tick. | 2056 // Give the tag a tick. |
2016 current->Tick(); | 2057 current->Tick(sample); |
2017 return current; | 2058 return current; |
2018 } | 2059 } |
2019 | 2060 |
2020 ProfileFunctionTrieNode* AppendVMTags(uword vm_tag, | 2061 ProfileFunctionTrieNode* AppendVMTags(uword vm_tag, |
2021 ProfileFunctionTrieNode* current) { | 2062 ProfileFunctionTrieNode* current, |
2022 current = AppendVMTag(vm_tag, current); | 2063 ProcessedSample* sample) { |
2023 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); | 2064 current = AppendVMTag(vm_tag, current, sample); |
2065 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); | |
2024 return current; | 2066 return current; |
2025 } | 2067 } |
2026 | 2068 |
2027 ProfileFunctionTrieNode* AppendExitFrame(uword vm_tag, | 2069 ProfileFunctionTrieNode* AppendExitFrame(uword vm_tag, |
2028 ProfileFunctionTrieNode* current) { | 2070 ProfileFunctionTrieNode* current, |
2071 ProcessedSample* sample) { | |
2029 if (FLAG_profile_vm) { | 2072 if (FLAG_profile_vm) { |
2030 return current; | 2073 return current; |
2031 } | 2074 } |
2032 | 2075 |
2033 if (!VMTag::IsExitFrameTag(vm_tag)) { | 2076 if (!VMTag::IsExitFrameTag(vm_tag)) { |
2034 return current; | 2077 return current; |
2035 } | 2078 } |
2036 if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) { | 2079 if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) { |
2037 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); | 2080 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); |
2038 } else { | 2081 } else { |
2039 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); | 2082 intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); |
2040 current = current->GetChild(tag_index); | 2083 current = current->GetChild(tag_index); |
2041 // Give the tag a tick. | 2084 // Give the tag a tick. |
2042 current->Tick(); | 2085 current->Tick(sample); |
2043 } | 2086 } |
2044 return current; | 2087 return current; |
2045 } | 2088 } |
2046 | 2089 |
2047 ProfileFunctionTrieNode* AppendTags(uword vm_tag, | 2090 ProfileFunctionTrieNode* AppendTags(uword vm_tag, |
2048 uword user_tag, | 2091 uword user_tag, |
2049 ProfileFunctionTrieNode* current) { | 2092 ProfileFunctionTrieNode* current, |
2093 ProcessedSample* sample) { | |
2050 if (FLAG_profile_vm) { | 2094 if (FLAG_profile_vm) { |
2051 // None. | 2095 // None. |
2052 if (tag_order() == Profile::kNoTags) { | 2096 if (tag_order() == Profile::kNoTags) { |
2053 return current; | 2097 return current; |
2054 } | 2098 } |
2055 // User first. | 2099 // User first. |
2056 if ((tag_order() == Profile::kUserVM) || | 2100 if ((tag_order() == Profile::kUserVM) || |
2057 (tag_order() == Profile::kUser)) { | 2101 (tag_order() == Profile::kUser)) { |
2058 current = AppendUserTag(user_tag, current); | 2102 current = AppendUserTag(user_tag, current, sample); |
2059 // Only user. | 2103 // Only user. |
2060 if (tag_order() == Profile::kUser) { | 2104 if (tag_order() == Profile::kUser) { |
2061 return current; | 2105 return current; |
2062 } | 2106 } |
2063 return AppendVMTags(vm_tag, current); | 2107 return AppendVMTags(vm_tag, current, sample); |
2064 } | 2108 } |
2065 // VM first. | 2109 // VM first. |
2066 ASSERT((tag_order() == Profile::kVMUser) || | 2110 ASSERT((tag_order() == Profile::kVMUser) || |
2067 (tag_order() == Profile::kVM)); | 2111 (tag_order() == Profile::kVM)); |
2068 current = AppendVMTags(vm_tag, current); | 2112 current = AppendVMTags(vm_tag, current, sample); |
2069 // Only VM. | 2113 // Only VM. |
2070 if (tag_order() == Profile::kVM) { | 2114 if (tag_order() == Profile::kVM) { |
2071 return current; | 2115 return current; |
2072 } | 2116 } |
2073 return AppendUserTag(user_tag, current); | 2117 return AppendUserTag(user_tag, current, sample); |
2074 } | 2118 } |
2075 | 2119 |
2076 if (tag_order() == Profile::kNoTags) { | 2120 if (tag_order() == Profile::kNoTags) { |
2077 return current; | 2121 return current; |
2078 } | 2122 } |
2079 | 2123 |
2080 return AppendUserTag(user_tag, current); | 2124 return AppendUserTag(user_tag, current, sample); |
2081 } | 2125 } |
2082 | 2126 |
2083 intptr_t GetProfileCodeTagIndex(uword tag) { | 2127 intptr_t GetProfileCodeTagIndex(uword tag) { |
2084 ProfileCodeTable* tag_table = profile_->tag_code_; | 2128 ProfileCodeTable* tag_table = profile_->tag_code_; |
2085 intptr_t index = tag_table->FindCodeIndexForPC(tag); | 2129 intptr_t index = tag_table->FindCodeIndexForPC(tag); |
2086 ASSERT(index >= 0); | 2130 ASSERT(index >= 0); |
2087 ProfileCode* code = tag_table->At(index); | 2131 ProfileCode* code = tag_table->At(index); |
2088 ASSERT(code != NULL); | 2132 ASSERT(code != NULL); |
2089 return code->code_table_index(); | 2133 return code->code_table_index(); |
2090 } | 2134 } |
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2720 (sample->allocation_cid() == cls_.id()); | 2764 (sample->allocation_cid() == cls_.id()); |
2721 } | 2765 } |
2722 | 2766 |
2723 private: | 2767 private: |
2724 const Class& cls_; | 2768 const Class& cls_; |
2725 }; | 2769 }; |
2726 | 2770 |
2727 | 2771 |
2728 class NativeAllocationSampleFilter : public SampleFilter { | 2772 class NativeAllocationSampleFilter : public SampleFilter { |
2729 public: | 2773 public: |
2730 NativeAllocationSampleFilter(intptr_t thread_task_mask, | 2774 NativeAllocationSampleFilter(int64_t time_origin_micros, |
2731 int64_t time_origin_micros, | |
2732 int64_t time_extent_micros) | 2775 int64_t time_extent_micros) |
2733 : SampleFilter(ILLEGAL_PORT, | 2776 : SampleFilter(ILLEGAL_PORT, |
2734 thread_task_mask, | 2777 SampleFilter::kNoTaskFilter, |
2735 time_origin_micros, | 2778 time_origin_micros, |
2736 time_extent_micros) {} | 2779 time_extent_micros) {} |
2737 bool FilterSample(Sample* sample) { | 2780 bool FilterSample(Sample* sample) { |
2738 return sample->is_native_allocation_sample(); | 2781 return sample->is_native_allocation_sample() && |
2782 !MallocHooks::NativeAllocationFreed( | |
2783 reinterpret_cast<void*>(sample->native_allocation_address())); | |
2739 } | 2784 } |
2740 }; | 2785 }; |
2741 | 2786 |
2742 | 2787 |
2743 void ProfilerService::PrintAllocationJSON(JSONStream* stream, | 2788 void ProfilerService::PrintAllocationJSON(JSONStream* stream, |
2744 Profile::TagOrder tag_order, | 2789 Profile::TagOrder tag_order, |
2745 const Class& cls, | 2790 const Class& cls, |
2746 int64_t time_origin_micros, | 2791 int64_t time_origin_micros, |
2747 int64_t time_extent_micros) { | 2792 int64_t time_extent_micros) { |
2748 Thread* thread = Thread::Current(); | 2793 Thread* thread = Thread::Current(); |
2749 Isolate* isolate = thread->isolate(); | 2794 Isolate* isolate = thread->isolate(); |
2750 ClassAllocationSampleFilter filter(isolate->main_port(), cls, | 2795 ClassAllocationSampleFilter filter(isolate->main_port(), cls, |
2751 Thread::kMutatorTask, time_origin_micros, | 2796 Thread::kMutatorTask, time_origin_micros, |
2752 time_extent_micros); | 2797 time_extent_micros); |
2753 const bool as_timeline = false; | 2798 const bool as_timeline = false; |
2754 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); | 2799 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); |
2755 } | 2800 } |
2756 | 2801 |
2757 | 2802 |
2758 void ProfilerService::PrintNativeAllocationJSON(JSONStream* stream, | 2803 void ProfilerService::PrintNativeAllocationJSON(JSONStream* stream, |
2759 Profile::TagOrder tag_order, | 2804 Profile::TagOrder tag_order, |
2760 int64_t time_origin_micros, | 2805 int64_t time_origin_micros, |
2761 int64_t time_extent_micros) { | 2806 int64_t time_extent_micros) { |
2762 Thread* thread = Thread::Current(); | 2807 Thread* thread = Thread::Current(); |
2763 const intptr_t thread_task_mask = Thread::kMutatorTask | | 2808 NativeAllocationSampleFilter filter(time_origin_micros, time_extent_micros); |
2764 Thread::kCompilerTask | | |
2765 Thread::kSweeperTask | Thread::kMarkerTask; | |
2766 NativeAllocationSampleFilter filter(thread_task_mask, time_origin_micros, | |
2767 time_extent_micros); | |
2768 const bool as_timeline = false; | 2809 const bool as_timeline = false; |
2769 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); | 2810 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); |
2770 } | 2811 } |
2771 | 2812 |
2772 | 2813 |
2773 void ProfilerService::PrintTimelineJSON(JSONStream* stream, | 2814 void ProfilerService::PrintTimelineJSON(JSONStream* stream, |
2774 Profile::TagOrder tag_order, | 2815 Profile::TagOrder tag_order, |
2775 int64_t time_origin_micros, | 2816 int64_t time_origin_micros, |
2776 int64_t time_extent_micros) { | 2817 int64_t time_extent_micros) { |
2777 Thread* thread = Thread::Current(); | 2818 Thread* thread = Thread::Current(); |
(...skipping 20 matching lines...) Expand all Loading... | |
2798 // Disable thread interrupts while processing the buffer. | 2839 // Disable thread interrupts while processing the buffer. |
2799 DisableThreadInterruptsScope dtis(thread); | 2840 DisableThreadInterruptsScope dtis(thread); |
2800 | 2841 |
2801 ClearProfileVisitor clear_profile(isolate); | 2842 ClearProfileVisitor clear_profile(isolate); |
2802 sample_buffer->VisitSamples(&clear_profile); | 2843 sample_buffer->VisitSamples(&clear_profile); |
2803 } | 2844 } |
2804 | 2845 |
2805 #endif // !PRODUCT | 2846 #endif // !PRODUCT |
2806 | 2847 |
2807 } // namespace dart | 2848 } // namespace dart |
OLD | NEW |