Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/profiler_service.h" | 5 #include "vm/profiler_service.h" |
| 6 | 6 |
| 7 #include "vm/growable_array.h" | 7 #include "vm/growable_array.h" |
| 8 #include "vm/native_symbol.h" | 8 #include "vm/native_symbol.h" |
| 9 #include "vm/object.h" | 9 #include "vm/object.h" |
| 10 #include "vm/os.h" | 10 #include "vm/os.h" |
| (...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 const char* tag_name = UserTags::TagName(start()); | 574 const char* tag_name = UserTags::TagName(start()); |
| 575 ASSERT(tag_name != NULL); | 575 ASSERT(tag_name != NULL); |
| 576 SetName(tag_name); | 576 SetName(tag_name); |
| 577 } else if (VMTag::IsVMTag(start()) || | 577 } else if (VMTag::IsVMTag(start()) || |
| 578 VMTag::IsRuntimeEntryTag(start()) || | 578 VMTag::IsRuntimeEntryTag(start()) || |
| 579 VMTag::IsNativeEntryTag(start())) { | 579 VMTag::IsNativeEntryTag(start())) { |
| 580 const char* tag_name = VMTag::TagName(start()); | 580 const char* tag_name = VMTag::TagName(start()); |
| 581 ASSERT(tag_name != NULL); | 581 ASSERT(tag_name != NULL); |
| 582 SetName(tag_name); | 582 SetName(tag_name); |
| 583 } else { | 583 } else { |
| 584 if (start() == VMTag::kRootTagId) { | 584 switch (start()) { |
| 585 SetName("Root"); | 585 case VMTag::kRootTagId: |
| 586 } else { | 586 SetName("Root"); |
| 587 ASSERT(start() == VMTag::kTruncatedTagId); | 587 break; |
| 588 SetName("[Truncated]"); | 588 case VMTag::kTruncatedTagId: |
| 589 SetName("[Truncated]"); | |
| 590 break; | |
| 591 case VMTag::kNoneCodeTagId: | |
| 592 SetName("[No Code]"); | |
| 593 break; | |
| 594 case VMTag::kOptimizedCodeTagId: | |
| 595 SetName("[Optimized Code]"); | |
| 596 break; | |
| 597 case VMTag::kUnoptimizedCodeTagId: | |
| 598 SetName("[Unoptimized Code]"); | |
| 599 break; | |
| 600 case VMTag::kNativeCodeTagId: | |
| 601 SetName("[Native Code]"); | |
| 602 break; | |
| 603 case VMTag::kInlineStartCodeTagId: | |
| 604 SetName("[Inline Start]"); | |
| 605 break; | |
| 606 case VMTag::kInlineEndCodeTagId: | |
| 607 SetName("[Inline End]"); | |
| 608 break; | |
| 609 default: | |
| 610 UNIMPLEMENTED(); | |
| 611 break; | |
| 589 } | 612 } |
| 590 } | 613 } |
| 591 } | 614 } |
| 592 function = table->AddTag(start(), name()); | 615 function = table->AddTag(start(), name()); |
| 593 } else { | 616 } else { |
| 594 UNREACHABLE(); | 617 UNREACHABLE(); |
| 595 } | 618 } |
| 596 ASSERT(function != NULL); | 619 ASSERT(function != NULL); |
| 597 | 620 |
| 598 function->AddProfileCode(code_table_index()); | 621 function->AddProfileCode(code_table_index()); |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 944 code_objects_.Add(code_object); | 967 code_objects_.Add(code_object); |
| 945 } | 968 } |
| 946 | 969 |
| 947 private: | 970 private: |
| 948 ZoneGrowableArray<ProfileFunctionTrieNodeCode> code_objects_; | 971 ZoneGrowableArray<ProfileFunctionTrieNodeCode> code_objects_; |
| 949 }; | 972 }; |
| 950 | 973 |
| 951 | 974 |
| 952 class ProfileBuilder : public ValueObject { | 975 class ProfileBuilder : public ValueObject { |
| 953 public: | 976 public: |
| 977 enum ProfileInfoKind { | |
| 978 kNone, | |
| 979 kOptimized, | |
| 980 kUnoptimized, | |
| 981 kNative, | |
| 982 kInlineStart, | |
| 983 kInlineFinish, | |
| 984 kNumProfileInfoKind, | |
| 985 }; | |
| 986 | |
| 954 ProfileBuilder(Isolate* isolate, | 987 ProfileBuilder(Isolate* isolate, |
| 955 SampleFilter* filter, | 988 SampleFilter* filter, |
| 956 Profile::TagOrder tag_order, | 989 Profile::TagOrder tag_order, |
| 990 intptr_t extra_tags, | |
| 957 Profile* profile) | 991 Profile* profile) |
| 958 : isolate_(isolate), | 992 : isolate_(isolate), |
| 959 vm_isolate_(Dart::vm_isolate()), | 993 vm_isolate_(Dart::vm_isolate()), |
| 960 filter_(filter), | 994 filter_(filter), |
| 961 tag_order_(tag_order), | 995 tag_order_(tag_order), |
| 996 extra_tags_(extra_tags), | |
| 962 profile_(profile), | 997 profile_(profile), |
| 963 deoptimized_code_(new DeoptimizedCodeSet(isolate)), | 998 deoptimized_code_(new DeoptimizedCodeSet(isolate)), |
| 964 null_code_(Code::ZoneHandle()), | 999 null_code_(Code::ZoneHandle()), |
| 965 null_function_(Function::ZoneHandle()), | 1000 null_function_(Function::ZoneHandle()), |
| 966 tick_functions_(false), | 1001 tick_functions_(false), |
| 967 inclusive_tree_(false), | 1002 inclusive_tree_(false), |
| 968 samples_(NULL) { | 1003 samples_(NULL), |
| 1004 info_kind_(kNone) { | |
| 969 ASSERT(profile_ != NULL); | 1005 ASSERT(profile_ != NULL); |
| 970 } | 1006 } |
| 971 | 1007 |
| 972 void Build() { | 1008 void Build() { |
| 973 ScopeTimer sw("ProfileBuilder::Build", FLAG_trace_profiler); | 1009 ScopeTimer sw("ProfileBuilder::Build", FLAG_trace_profiler); |
| 974 FilterSamples(); | 1010 FilterSamples(); |
| 975 | 1011 |
| 976 Setup(); | 1012 Setup(); |
| 977 BuildCodeTable(); | 1013 BuildCodeTable(); |
| 978 FinalizeCodeIndexes(); | 1014 FinalizeCodeIndexes(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 998 } | 1034 } |
| 999 | 1035 |
| 1000 void Setup() { | 1036 void Setup() { |
| 1001 profile_->live_code_ = new ProfileCodeTable(); | 1037 profile_->live_code_ = new ProfileCodeTable(); |
| 1002 profile_->dead_code_ = new ProfileCodeTable(); | 1038 profile_->dead_code_ = new ProfileCodeTable(); |
| 1003 profile_->tag_code_ = new ProfileCodeTable(); | 1039 profile_->tag_code_ = new ProfileCodeTable(); |
| 1004 profile_->functions_ = new ProfileFunctionTable(); | 1040 profile_->functions_ = new ProfileFunctionTable(); |
| 1005 // Register some synthetic tags. | 1041 // Register some synthetic tags. |
| 1006 RegisterProfileCodeTag(VMTag::kRootTagId); | 1042 RegisterProfileCodeTag(VMTag::kRootTagId); |
| 1007 RegisterProfileCodeTag(VMTag::kTruncatedTagId); | 1043 RegisterProfileCodeTag(VMTag::kTruncatedTagId); |
| 1044 RegisterProfileCodeTag(VMTag::kNoneCodeTagId); | |
| 1045 RegisterProfileCodeTag(VMTag::kOptimizedCodeTagId); | |
| 1046 RegisterProfileCodeTag(VMTag::kUnoptimizedCodeTagId); | |
| 1047 RegisterProfileCodeTag(VMTag::kNativeCodeTagId); | |
| 1048 RegisterProfileCodeTag(VMTag::kInlineStartCodeTagId); | |
| 1049 RegisterProfileCodeTag(VMTag::kInlineEndCodeTagId); | |
| 1008 } | 1050 } |
| 1009 | 1051 |
| 1010 void FilterSamples() { | 1052 void FilterSamples() { |
| 1011 ScopeTimer sw("ProfileBuilder::FilterSamples", FLAG_trace_profiler); | 1053 ScopeTimer sw("ProfileBuilder::FilterSamples", FLAG_trace_profiler); |
| 1012 MutexLocker profiler_data_lock(isolate_->profiler_data_mutex()); | 1054 MutexLocker profiler_data_lock(isolate_->profiler_data_mutex()); |
| 1013 IsolateProfilerData* profiler_data = isolate_->profiler_data(); | 1055 IsolateProfilerData* profiler_data = isolate_->profiler_data(); |
| 1014 if (profiler_data == NULL) { | 1056 if (profiler_data == NULL) { |
| 1015 return; | 1057 return; |
| 1016 } | 1058 } |
| 1017 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); | 1059 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1145 sample_index++) { | 1187 sample_index++) { |
| 1146 ProcessedSample* sample = samples_->At(sample_index); | 1188 ProcessedSample* sample = samples_->At(sample_index); |
| 1147 | 1189 |
| 1148 // Tick the root. | 1190 // Tick the root. |
| 1149 ProfileCodeTrieNode* current = root; | 1191 ProfileCodeTrieNode* current = root; |
| 1150 current->Tick(); | 1192 current->Tick(); |
| 1151 | 1193 |
| 1152 // VM & User tags. | 1194 // VM & User tags. |
| 1153 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); | 1195 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); |
| 1154 | 1196 |
| 1197 ResetKind(); | |
| 1198 | |
| 1155 // Truncated tag. | 1199 // Truncated tag. |
| 1156 if (sample->truncated()) { | 1200 if (sample->truncated()) { |
| 1157 current = AppendTruncatedTag(current); | 1201 current = AppendTruncatedTag(current); |
| 1158 } | 1202 } |
| 1159 | 1203 |
| 1160 // Walk the sampled PCs. | 1204 // Walk the sampled PCs. |
| 1205 Code& code = Code::Handle(); | |
| 1161 for (intptr_t frame_index = sample->length() - 1; | 1206 for (intptr_t frame_index = sample->length() - 1; |
| 1162 frame_index >= 0; | 1207 frame_index >= 0; |
| 1163 frame_index--) { | 1208 frame_index--) { |
| 1164 ASSERT(sample->At(frame_index) != 0); | 1209 ASSERT(sample->At(frame_index) != 0); |
| 1165 intptr_t index = | 1210 intptr_t index = |
| 1166 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); | 1211 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); |
| 1167 ASSERT(index >= 0); | 1212 ASSERT(index >= 0); |
| 1213 ProfileCode* profile_code = | |
| 1214 GetProfileCode(sample->At(frame_index), sample->timestamp()); | |
| 1215 ASSERT(profile_code->code_table_index() == index); | |
| 1216 code ^= profile_code->code(); | |
| 1217 current = AppendKind(code, current); | |
| 1168 current = current->GetChild(index); | 1218 current = current->GetChild(index); |
| 1169 current->Tick(); | 1219 current->Tick(); |
| 1170 } | 1220 } |
| 1171 } | 1221 } |
| 1172 } | 1222 } |
| 1173 | 1223 |
| 1174 void BuildExclusiveCodeTrie(ProfileCodeTrieNode* root) { | 1224 void BuildExclusiveCodeTrie(ProfileCodeTrieNode* root) { |
| 1175 ScopeTimer sw("ProfileBuilder::BuildExclusiveCodeTrie", | 1225 ScopeTimer sw("ProfileBuilder::BuildExclusiveCodeTrie", |
| 1176 FLAG_trace_profiler); | 1226 FLAG_trace_profiler); |
| 1177 for (intptr_t sample_index = 0; | 1227 for (intptr_t sample_index = 0; |
| 1178 sample_index < samples_->length(); | 1228 sample_index < samples_->length(); |
| 1179 sample_index++) { | 1229 sample_index++) { |
| 1180 ProcessedSample* sample = samples_->At(sample_index); | 1230 ProcessedSample* sample = samples_->At(sample_index); |
| 1181 | 1231 |
| 1182 // Tick the root. | 1232 // Tick the root. |
| 1183 ProfileCodeTrieNode* current = root; | 1233 ProfileCodeTrieNode* current = root; |
| 1184 current->Tick(); | 1234 current->Tick(); |
| 1185 | 1235 |
| 1186 // VM & User tags. | 1236 // VM & User tags. |
| 1187 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); | 1237 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); |
| 1188 | 1238 |
| 1239 ResetKind(); | |
| 1240 | |
| 1189 // Walk the sampled PCs. | 1241 // Walk the sampled PCs. |
| 1242 Code& code = Code::Handle(); | |
| 1190 for (intptr_t frame_index = 0; | 1243 for (intptr_t frame_index = 0; |
| 1191 frame_index < sample->length(); | 1244 frame_index < sample->length(); |
| 1192 frame_index++) { | 1245 frame_index++) { |
| 1193 ASSERT(sample->At(frame_index) != 0); | 1246 ASSERT(sample->At(frame_index) != 0); |
| 1194 intptr_t index = | 1247 intptr_t index = |
| 1195 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); | 1248 GetProfileCodeIndex(sample->At(frame_index), sample->timestamp()); |
| 1196 ASSERT(index >= 0); | 1249 ASSERT(index >= 0); |
| 1250 ProfileCode* profile_code = | |
| 1251 GetProfileCode(sample->At(frame_index), sample->timestamp()); | |
| 1252 ASSERT(profile_code->code_table_index() == index); | |
| 1253 code ^= profile_code->code(); | |
| 1197 current = current->GetChild(index); | 1254 current = current->GetChild(index); |
| 1198 if (ShouldTickNode(sample, frame_index)) { | 1255 if (ShouldTickNode(sample, frame_index)) { |
| 1199 current->Tick(); | 1256 current->Tick(); |
| 1200 } | 1257 } |
| 1258 current = AppendKind(code, current); | |
| 1201 } | 1259 } |
| 1202 // Truncated tag. | 1260 // Truncated tag. |
| 1203 if (sample->truncated()) { | 1261 if (sample->truncated()) { |
| 1204 current = AppendTruncatedTag(current); | 1262 current = AppendTruncatedTag(current); |
| 1205 } | 1263 } |
| 1206 } | 1264 } |
| 1207 } | 1265 } |
| 1208 | 1266 |
| 1209 void BuildFunctionTrie(Profile::TrieKind kind) { | 1267 void BuildFunctionTrie(Profile::TrieKind kind) { |
| 1210 ProfileFunctionTrieNode* root = | 1268 ProfileFunctionTrieNode* root = |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1263 sample_index++) { | 1321 sample_index++) { |
| 1264 ProcessedSample* sample = samples_->At(sample_index); | 1322 ProcessedSample* sample = samples_->At(sample_index); |
| 1265 | 1323 |
| 1266 // Tick the root. | 1324 // Tick the root. |
| 1267 ProfileFunctionTrieNode* current = root; | 1325 ProfileFunctionTrieNode* current = root; |
| 1268 current->Tick(); | 1326 current->Tick(); |
| 1269 | 1327 |
| 1270 // VM & User tags. | 1328 // VM & User tags. |
| 1271 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); | 1329 current = AppendTags(sample->vm_tag(), sample->user_tag(), current); |
| 1272 | 1330 |
| 1331 ResetKind(); | |
| 1332 | |
| 1273 // Walk the sampled PCs. | 1333 // Walk the sampled PCs. |
| 1274 for (intptr_t frame_index = 0; | 1334 for (intptr_t frame_index = 0; |
| 1275 frame_index < sample->length(); | 1335 frame_index < sample->length(); |
| 1276 frame_index++) { | 1336 frame_index++) { |
| 1277 ASSERT(sample->At(frame_index) != 0); | 1337 ASSERT(sample->At(frame_index) != 0); |
| 1278 current = ProcessFrame(current, sample_index, sample, frame_index); | 1338 current = ProcessFrame(current, sample_index, sample, frame_index); |
| 1279 } | 1339 } |
| 1280 | 1340 |
| 1281 // Truncated tag. | 1341 // Truncated tag. |
| 1282 if (sample->truncated()) { | 1342 if (sample->truncated()) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1299 const intptr_t code_index = profile_code->code_table_index(); | 1359 const intptr_t code_index = profile_code->code_table_index(); |
| 1300 ASSERT(profile_code != NULL); | 1360 ASSERT(profile_code != NULL); |
| 1301 const Code& code = Code::ZoneHandle(profile_code->code()); | 1361 const Code& code = Code::ZoneHandle(profile_code->code()); |
| 1302 GrowableArray<Function*> inlined_functions; | 1362 GrowableArray<Function*> inlined_functions; |
| 1303 if (!code.IsNull()) { | 1363 if (!code.IsNull()) { |
| 1304 intptr_t offset = pc - code.EntryPoint(); | 1364 intptr_t offset = pc - code.EntryPoint(); |
| 1305 code.GetInlinedFunctionsAt(offset, &inlined_functions); | 1365 code.GetInlinedFunctionsAt(offset, &inlined_functions); |
| 1306 } | 1366 } |
| 1307 if (code.IsNull() || (inlined_functions.length() == 0)) { | 1367 if (code.IsNull() || (inlined_functions.length() == 0)) { |
| 1308 // No inlined functions. | 1368 // No inlined functions. |
| 1369 if (inclusive_tree_) { | |
| 1370 current = AppendKind(code, current); | |
| 1371 } | |
| 1309 current = ProcessFunction(current, | 1372 current = ProcessFunction(current, |
| 1310 sample_index, | 1373 sample_index, |
| 1311 sample, | 1374 sample, |
| 1312 frame_index, | 1375 frame_index, |
| 1313 function, | 1376 function, |
| 1314 code_index); | 1377 code_index); |
| 1378 if (!inclusive_tree_) { | |
| 1379 current = AppendKind(code, current); | |
| 1380 } | |
| 1315 return current; | 1381 return current; |
| 1316 } | 1382 } |
| 1317 | 1383 |
| 1384 ASSERT(code.is_optimized()); | |
| 1385 | |
| 1318 if (inclusive_tree_) { | 1386 if (inclusive_tree_) { |
| 1319 // Append the inlined children. | |
| 1320 for (intptr_t i = inlined_functions.length() - 1; i >= 0; i--) { | 1387 for (intptr_t i = inlined_functions.length() - 1; i >= 0; i--) { |
| 1321 Function* inlined_function = inlined_functions[i]; | 1388 Function* inlined_function = inlined_functions[i]; |
| 1322 ASSERT(inlined_function != NULL); | 1389 ASSERT(inlined_function != NULL); |
| 1323 ASSERT(!inlined_function->IsNull()); | 1390 ASSERT(!inlined_function->IsNull()); |
| 1391 const bool inliner = i == (inlined_functions.length() - 1); | |
| 1392 if (inliner) { | |
| 1393 current = AppendKind(code, current); | |
| 1394 } | |
| 1324 current = ProcessInlinedFunction(current, | 1395 current = ProcessInlinedFunction(current, |
| 1325 sample_index, | 1396 sample_index, |
| 1326 sample, | 1397 sample, |
| 1327 frame_index, | 1398 frame_index, |
| 1328 inlined_function, | 1399 inlined_function, |
| 1329 code_index); | 1400 code_index); |
| 1401 if (inliner) { | |
| 1402 current = AppendKind(kInlineStart, current); | |
| 1403 } | |
| 1330 } | 1404 } |
| 1405 current = AppendKind(kInlineFinish, current); | |
| 1331 } else { | 1406 } else { |
| 1332 // Append the inlined children. | 1407 // Append the inlined children. |
| 1408 current = AppendKind(kInlineFinish, current); | |
| 1333 for (intptr_t i = 0; i < inlined_functions.length(); i++) { | 1409 for (intptr_t i = 0; i < inlined_functions.length(); i++) { |
| 1334 Function* inlined_function = inlined_functions[i]; | 1410 Function* inlined_function = inlined_functions[i]; |
| 1335 ASSERT(inlined_function != NULL); | 1411 ASSERT(inlined_function != NULL); |
| 1336 ASSERT(!inlined_function->IsNull()); | 1412 ASSERT(!inlined_function->IsNull()); |
| 1413 const bool inliner = i == (inlined_functions.length() - 1); | |
| 1414 if (inliner) { | |
| 1415 current = AppendKind(kInlineStart, current); | |
| 1416 } | |
| 1337 current = ProcessInlinedFunction(current, | 1417 current = ProcessInlinedFunction(current, |
| 1338 sample_index, | 1418 sample_index, |
| 1339 sample, | 1419 sample, |
| 1340 frame_index + i, | 1420 frame_index + i, |
| 1341 inlined_function, | 1421 inlined_function, |
| 1342 code_index); | 1422 code_index); |
| 1423 if (inliner) { | |
| 1424 current = AppendKind(code, current); | |
| 1425 } | |
| 1343 } | 1426 } |
| 1344 } | 1427 } |
| 1345 | 1428 |
| 1346 return current; | 1429 return current; |
| 1347 } | 1430 } |
| 1348 | 1431 |
| 1349 ProfileFunctionTrieNode* ProcessInlinedFunction( | 1432 ProfileFunctionTrieNode* ProcessInlinedFunction( |
| 1350 ProfileFunctionTrieNode* current, | 1433 ProfileFunctionTrieNode* current, |
| 1351 intptr_t sample_index, | 1434 intptr_t sample_index, |
| 1352 ProcessedSample* sample, | 1435 ProcessedSample* sample, |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1457 !VMTag::IsRuntimeEntryTag(vm_tag)) { | 1540 !VMTag::IsRuntimeEntryTag(vm_tag)) { |
| 1458 return current; | 1541 return current; |
| 1459 } | 1542 } |
| 1460 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); | 1543 intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); |
| 1461 current = current->GetChild(tag_index); | 1544 current = current->GetChild(tag_index); |
| 1462 // Give the tag a tick. | 1545 // Give the tag a tick. |
| 1463 current->Tick(); | 1546 current->Tick(); |
| 1464 return current; | 1547 return current; |
| 1465 } | 1548 } |
| 1466 | 1549 |
| 1550 uword ProfileInfoKindToVMTag(ProfileInfoKind kind) { | |
| 1551 ASSERT(kNone == 0); | |
| 1552 ASSERT(kOptimized == 1); | |
| 1553 ASSERT(kUnoptimized == 2); | |
| 1554 ASSERT(kNative == 3); | |
| 1555 ASSERT(kInlineStart == 4); | |
| 1556 ASSERT(kInlineFinish == 5); | |
| 1557 ASSERT(kNumProfileInfoKind == 6); | |
| 1558 uword tag_map[] = { | |
|
srdjan
2015/08/04 21:24:46
'static uword tag_map', so that it does not get co
Cutch
2015/08/04 22:00:58
Done.
| |
| 1559 VMTag::kNoneCodeTagId, | |
| 1560 VMTag::kOptimizedCodeTagId, | |
| 1561 VMTag::kUnoptimizedCodeTagId, | |
| 1562 VMTag::kNativeCodeTagId, | |
| 1563 VMTag::kInlineStartCodeTagId, | |
| 1564 VMTag::kInlineEndCodeTagId, | |
| 1565 VMTag::kInvalidTagId | |
| 1566 }; | |
| 1567 return tag_map[kind]; | |
| 1568 } | |
| 1569 | |
| 1570 ProfileCodeTrieNode* AppendKind(ProfileInfoKind kind, | |
| 1571 ProfileCodeTrieNode* current) { | |
| 1572 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { | |
| 1573 // Only emit if debug tags are requested. | |
| 1574 return current; | |
| 1575 } | |
| 1576 if (kind != info_kind_) { | |
| 1577 info_kind_ = kind; | |
| 1578 intptr_t tag_index = GetProfileCodeTagIndex(ProfileInfoKindToVMTag(kind)); | |
| 1579 ASSERT(tag_index >= 0); | |
| 1580 current = current->GetChild(tag_index); | |
| 1581 current->Tick(); | |
| 1582 } | |
| 1583 return current; | |
| 1584 } | |
| 1585 | |
| 1586 ProfileCodeTrieNode* AppendKind(const Code& code, | |
| 1587 ProfileCodeTrieNode* current) { | |
| 1588 if (code.IsNull()) { | |
| 1589 return AppendKind(kNone, current); | |
| 1590 } else if (code.is_optimized()) { | |
| 1591 return AppendKind(kOptimized, current); | |
| 1592 } else { | |
| 1593 return AppendKind(kUnoptimized, current); | |
| 1594 } | |
| 1595 } | |
| 1596 | |
| 1467 ProfileCodeTrieNode* AppendVMTags(uword vm_tag, | 1597 ProfileCodeTrieNode* AppendVMTags(uword vm_tag, |
| 1468 ProfileCodeTrieNode* current) { | 1598 ProfileCodeTrieNode* current) { |
| 1469 current = AppendVMTag(vm_tag, current); | 1599 current = AppendVMTag(vm_tag, current); |
| 1470 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); | 1600 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); |
| 1471 return current; | 1601 return current; |
| 1472 } | 1602 } |
| 1473 | 1603 |
| 1474 ProfileCodeTrieNode* AppendTags(uword vm_tag, | 1604 ProfileCodeTrieNode* AppendTags(uword vm_tag, |
| 1475 uword user_tag, | 1605 uword user_tag, |
| 1476 ProfileCodeTrieNode* current) { | 1606 ProfileCodeTrieNode* current) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1493 (tag_order() == Profile::kVM)); | 1623 (tag_order() == Profile::kVM)); |
| 1494 current = AppendVMTags(vm_tag, current); | 1624 current = AppendVMTags(vm_tag, current); |
| 1495 // Only VM. | 1625 // Only VM. |
| 1496 if (tag_order() == Profile::kVM) { | 1626 if (tag_order() == Profile::kVM) { |
| 1497 return current; | 1627 return current; |
| 1498 } | 1628 } |
| 1499 return AppendUserTag(user_tag, current); | 1629 return AppendUserTag(user_tag, current); |
| 1500 } | 1630 } |
| 1501 | 1631 |
| 1502 // ProfileFunctionTrieNode | 1632 // ProfileFunctionTrieNode |
| 1633 void ResetKind() { | |
| 1634 info_kind_ = kNone; | |
| 1635 } | |
| 1636 | |
| 1637 ProfileFunctionTrieNode* AppendKind(ProfileInfoKind kind, | |
| 1638 ProfileFunctionTrieNode* current) { | |
| 1639 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { | |
| 1640 // Only emit if debug tags are requested. | |
| 1641 return current; | |
| 1642 } | |
| 1643 if (kind != info_kind_) { | |
| 1644 info_kind_ = kind; | |
| 1645 intptr_t tag_index = | |
| 1646 GetProfileFunctionTagIndex(ProfileInfoKindToVMTag(kind)); | |
| 1647 ASSERT(tag_index >= 0); | |
| 1648 current = current->GetChild(tag_index); | |
| 1649 current->Tick(); | |
| 1650 } | |
| 1651 return current; | |
| 1652 } | |
| 1653 | |
| 1654 ProfileFunctionTrieNode* AppendKind(const Code& code, | |
| 1655 ProfileFunctionTrieNode* current) { | |
| 1656 if (code.IsNull()) { | |
| 1657 return AppendKind(kNone, current); | |
| 1658 } else if (code.is_optimized()) { | |
| 1659 return AppendKind(kOptimized, current); | |
| 1660 } else { | |
| 1661 return AppendKind(kUnoptimized, current); | |
| 1662 } | |
| 1663 } | |
| 1664 | |
| 1503 ProfileFunctionTrieNode* AppendUserTag(uword user_tag, | 1665 ProfileFunctionTrieNode* AppendUserTag(uword user_tag, |
| 1504 ProfileFunctionTrieNode* current) { | 1666 ProfileFunctionTrieNode* current) { |
| 1505 intptr_t user_tag_index = GetProfileFunctionTagIndex(user_tag); | 1667 intptr_t user_tag_index = GetProfileFunctionTagIndex(user_tag); |
| 1506 if (user_tag_index >= 0) { | 1668 if (user_tag_index >= 0) { |
| 1507 current = current->GetChild(user_tag_index); | 1669 current = current->GetChild(user_tag_index); |
| 1508 current->Tick(); | 1670 current->Tick(); |
| 1509 } | 1671 } |
| 1510 return current; | 1672 return current; |
| 1511 } | 1673 } |
| 1512 | 1674 |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1776 Profile::TagOrder tag_order() const { | 1938 Profile::TagOrder tag_order() const { |
| 1777 return tag_order_; | 1939 return tag_order_; |
| 1778 } | 1940 } |
| 1779 | 1941 |
| 1780 bool vm_tags_emitted() const { | 1942 bool vm_tags_emitted() const { |
| 1781 return (tag_order_ == Profile::kUserVM) || | 1943 return (tag_order_ == Profile::kUserVM) || |
| 1782 (tag_order_ == Profile::kVMUser) || | 1944 (tag_order_ == Profile::kVMUser) || |
| 1783 (tag_order_ == Profile::kVM); | 1945 (tag_order_ == Profile::kVM); |
| 1784 } | 1946 } |
| 1785 | 1947 |
| 1948 bool TagsEnabled(intptr_t extra_tags_bits) { | |
|
srdjan
2015/08/04 21:24:46
const
Cutch
2015/08/04 22:00:58
Done.
| |
| 1949 return (extra_tags_ & extra_tags_bits) != 0; | |
| 1950 } | |
| 1951 | |
| 1786 Isolate* isolate_; | 1952 Isolate* isolate_; |
| 1787 Isolate* vm_isolate_; | 1953 Isolate* vm_isolate_; |
| 1788 SampleFilter* filter_; | 1954 SampleFilter* filter_; |
| 1789 Profile::TagOrder tag_order_; | 1955 Profile::TagOrder tag_order_; |
| 1956 intptr_t extra_tags_; | |
| 1790 Profile* profile_; | 1957 Profile* profile_; |
| 1791 DeoptimizedCodeSet* deoptimized_code_; | 1958 DeoptimizedCodeSet* deoptimized_code_; |
| 1792 const Code& null_code_; | 1959 const Code& null_code_; |
| 1793 const Function& null_function_; | 1960 const Function& null_function_; |
| 1794 bool tick_functions_; | 1961 bool tick_functions_; |
| 1795 bool inclusive_tree_; | 1962 bool inclusive_tree_; |
| 1796 | 1963 |
| 1797 ProcessedSampleBuffer* samples_; | 1964 ProcessedSampleBuffer* samples_; |
| 1965 ProfileInfoKind info_kind_; | |
| 1798 }; | 1966 }; |
| 1799 | 1967 |
| 1800 | 1968 |
| 1801 Profile::Profile(Isolate* isolate) | 1969 Profile::Profile(Isolate* isolate) |
| 1802 : isolate_(isolate), | 1970 : isolate_(isolate), |
| 1803 live_code_(NULL), | 1971 live_code_(NULL), |
| 1804 dead_code_(NULL), | 1972 dead_code_(NULL), |
| 1805 tag_code_(NULL), | 1973 tag_code_(NULL), |
| 1806 functions_(NULL), | 1974 functions_(NULL), |
| 1807 dead_code_index_offset_(-1), | 1975 dead_code_index_offset_(-1), |
| 1808 tag_code_index_offset_(-1), | 1976 tag_code_index_offset_(-1), |
| 1809 min_time_(kMaxInt64), | 1977 min_time_(kMaxInt64), |
| 1810 max_time_(0) { | 1978 max_time_(0) { |
| 1811 ASSERT(isolate_ != NULL); | 1979 ASSERT(isolate_ != NULL); |
| 1812 for (intptr_t i = 0; i < kNumTrieKinds; i++) { | 1980 for (intptr_t i = 0; i < kNumTrieKinds; i++) { |
| 1813 roots_[i] = NULL; | 1981 roots_[i] = NULL; |
| 1814 } | 1982 } |
| 1815 } | 1983 } |
| 1816 | 1984 |
| 1817 | 1985 |
| 1818 void Profile::Build(SampleFilter* filter, TagOrder tag_order) { | 1986 void Profile::Build(SampleFilter* filter, |
| 1819 ProfileBuilder builder(isolate_, filter, tag_order, this); | 1987 TagOrder tag_order, |
| 1988 intptr_t extra_tags) { | |
| 1989 ProfileBuilder builder(isolate_, filter, tag_order, extra_tags, this); | |
| 1820 builder.Build(); | 1990 builder.Build(); |
| 1821 } | 1991 } |
| 1822 | 1992 |
| 1823 | 1993 |
| 1824 ProfileFunction* Profile::GetFunction(intptr_t index) { | 1994 ProfileFunction* Profile::GetFunction(intptr_t index) { |
| 1825 ASSERT(functions_ != NULL); | 1995 ASSERT(functions_ != NULL); |
| 1826 return functions_->At(index); | 1996 return functions_->At(index); |
| 1827 } | 1997 } |
| 1828 | 1998 |
| 1829 | 1999 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2012 | 2182 |
| 2013 intptr_t ProfileTrieWalker::SiblingCount() { | 2183 intptr_t ProfileTrieWalker::SiblingCount() { |
| 2014 ASSERT(parent_ != NULL); | 2184 ASSERT(parent_ != NULL); |
| 2015 return parent_->NumChildren(); | 2185 return parent_->NumChildren(); |
| 2016 } | 2186 } |
| 2017 | 2187 |
| 2018 | 2188 |
| 2019 void ProfilerService::PrintJSONImpl(Isolate* isolate, | 2189 void ProfilerService::PrintJSONImpl(Isolate* isolate, |
| 2020 JSONStream* stream, | 2190 JSONStream* stream, |
| 2021 Profile::TagOrder tag_order, | 2191 Profile::TagOrder tag_order, |
| 2192 intptr_t extra_tags, | |
| 2022 SampleFilter* filter) { | 2193 SampleFilter* filter) { |
| 2023 // Disable profile interrupts while processing the buffer. | 2194 // Disable profile interrupts while processing the buffer. |
| 2024 Profiler::EndExecution(isolate); | 2195 Profiler::EndExecution(isolate); |
| 2025 | 2196 |
| 2026 { | 2197 { |
| 2027 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); | 2198 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); |
| 2028 IsolateProfilerData* profiler_data = isolate->profiler_data(); | 2199 IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| 2029 if (profiler_data == NULL) { | 2200 if (profiler_data == NULL) { |
| 2030 stream->PrintError(kFeatureDisabled, NULL); | 2201 stream->PrintError(kFeatureDisabled, NULL); |
| 2031 return; | 2202 return; |
| 2032 } | 2203 } |
| 2033 } | 2204 } |
| 2034 | 2205 |
| 2035 { | 2206 { |
| 2036 StackZone zone(isolate); | 2207 StackZone zone(isolate); |
| 2037 HANDLESCOPE(isolate); | 2208 HANDLESCOPE(isolate); |
| 2038 Profile profile(isolate); | 2209 Profile profile(isolate); |
| 2039 profile.Build(filter, tag_order); | 2210 profile.Build(filter, tag_order, extra_tags); |
| 2040 profile.PrintJSON(stream); | 2211 profile.PrintJSON(stream); |
| 2041 } | 2212 } |
| 2042 | 2213 |
| 2043 // Enable profile interrupts. | 2214 // Enable profile interrupts. |
| 2044 Profiler::BeginExecution(isolate); | 2215 Profiler::BeginExecution(isolate); |
| 2045 } | 2216 } |
| 2046 | 2217 |
| 2047 | 2218 |
| 2048 class NoAllocationSampleFilter : public SampleFilter { | 2219 class NoAllocationSampleFilter : public SampleFilter { |
| 2049 public: | 2220 public: |
| 2050 explicit NoAllocationSampleFilter(Isolate* isolate) | 2221 explicit NoAllocationSampleFilter(Isolate* isolate) |
| 2051 : SampleFilter(isolate) { | 2222 : SampleFilter(isolate) { |
| 2052 } | 2223 } |
| 2053 | 2224 |
| 2054 bool FilterSample(Sample* sample) { | 2225 bool FilterSample(Sample* sample) { |
| 2055 return !sample->is_allocation_sample(); | 2226 return !sample->is_allocation_sample(); |
| 2056 } | 2227 } |
| 2057 }; | 2228 }; |
| 2058 | 2229 |
| 2059 | 2230 |
| 2060 void ProfilerService::PrintJSON(JSONStream* stream, | 2231 void ProfilerService::PrintJSON(JSONStream* stream, |
| 2061 Profile::TagOrder tag_order) { | 2232 Profile::TagOrder tag_order, |
| 2233 intptr_t extra_tags) { | |
| 2062 Isolate* isolate = Isolate::Current(); | 2234 Isolate* isolate = Isolate::Current(); |
| 2063 NoAllocationSampleFilter filter(isolate); | 2235 NoAllocationSampleFilter filter(isolate); |
| 2064 PrintJSONImpl(isolate, stream, tag_order, &filter); | 2236 PrintJSONImpl(isolate, stream, tag_order, extra_tags, &filter); |
| 2065 } | 2237 } |
| 2066 | 2238 |
| 2067 | 2239 |
| 2068 class ClassAllocationSampleFilter : public SampleFilter { | 2240 class ClassAllocationSampleFilter : public SampleFilter { |
| 2069 public: | 2241 public: |
| 2070 ClassAllocationSampleFilter(Isolate* isolate, const Class& cls) | 2242 ClassAllocationSampleFilter(Isolate* isolate, const Class& cls) |
| 2071 : SampleFilter(isolate), | 2243 : SampleFilter(isolate), |
| 2072 cls_(Class::Handle(cls.raw())) { | 2244 cls_(Class::Handle(cls.raw())) { |
| 2073 ASSERT(!cls_.IsNull()); | 2245 ASSERT(!cls_.IsNull()); |
| 2074 } | 2246 } |
| 2075 | 2247 |
| 2076 bool FilterSample(Sample* sample) { | 2248 bool FilterSample(Sample* sample) { |
| 2077 return sample->is_allocation_sample() && | 2249 return sample->is_allocation_sample() && |
| 2078 (sample->allocation_cid() == cls_.id()); | 2250 (sample->allocation_cid() == cls_.id()); |
| 2079 } | 2251 } |
| 2080 | 2252 |
| 2081 private: | 2253 private: |
| 2082 const Class& cls_; | 2254 const Class& cls_; |
| 2083 }; | 2255 }; |
| 2084 | 2256 |
| 2085 | 2257 |
| 2086 void ProfilerService::PrintAllocationJSON(JSONStream* stream, | 2258 void ProfilerService::PrintAllocationJSON(JSONStream* stream, |
| 2087 Profile::TagOrder tag_order, | 2259 Profile::TagOrder tag_order, |
| 2088 const Class& cls) { | 2260 const Class& cls) { |
| 2089 Isolate* isolate = Isolate::Current(); | 2261 Isolate* isolate = Isolate::Current(); |
| 2090 ClassAllocationSampleFilter filter(isolate, cls); | 2262 ClassAllocationSampleFilter filter(isolate, cls); |
| 2091 PrintJSONImpl(isolate, stream, tag_order, &filter); | 2263 PrintJSONImpl(isolate, stream, tag_order, 0, &filter); |
|
srdjan
2015/08/04 21:24:46
kNone instead of 0?
Cutch
2015/08/04 22:00:58
Done.
| |
| 2092 } | 2264 } |
| 2093 | 2265 |
| 2094 | 2266 |
| 2095 void ProfilerService::ClearSamples() { | 2267 void ProfilerService::ClearSamples() { |
| 2096 Isolate* isolate = Isolate::Current(); | 2268 Isolate* isolate = Isolate::Current(); |
| 2097 | 2269 |
| 2098 // Disable profile interrupts while processing the buffer. | 2270 // Disable profile interrupts while processing the buffer. |
| 2099 Profiler::EndExecution(isolate); | 2271 Profiler::EndExecution(isolate); |
| 2100 | 2272 |
| 2101 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); | 2273 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); |
| 2102 IsolateProfilerData* profiler_data = isolate->profiler_data(); | 2274 IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| 2103 if (profiler_data == NULL) { | 2275 if (profiler_data == NULL) { |
| 2104 return; | 2276 return; |
| 2105 } | 2277 } |
| 2106 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); | 2278 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); |
| 2107 ASSERT(sample_buffer != NULL); | 2279 ASSERT(sample_buffer != NULL); |
| 2108 | 2280 |
| 2109 ClearProfileVisitor clear_profile(isolate); | 2281 ClearProfileVisitor clear_profile(isolate); |
| 2110 sample_buffer->VisitSamples(&clear_profile); | 2282 sample_buffer->VisitSamples(&clear_profile); |
| 2111 | 2283 |
| 2112 // Enable profile interrupts. | 2284 // Enable profile interrupts. |
| 2113 Profiler::BeginExecution(isolate); | 2285 Profiler::BeginExecution(isolate); |
| 2114 } | 2286 } |
| 2115 | 2287 |
| 2116 } // namespace dart | 2288 } // namespace dart |
| OLD | NEW |