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 kNumProfileInfoTag, | |
|
srdjan
2015/08/04 18:37:15
s/Tag/Kind/
Does the order must be the same as in
Cutch
2015/08/04 21:19:08
Done. The ordering only matters in the mapping tab
| |
| 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); | |
|
srdjan
2015/08/04 18:37:15
Does the order of registration matter?
Cutch
2015/08/04 21:19:08
No.
| |
| 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; | |
|
srdjan
2015/08/04 18:37:15
i == (inlined_functions.length() - 1)
Cutch
2015/08/04 21:19:08
Done.
| |
| 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; | |
|
srdjan
2015/08/04 18:37:16
ditto
Cutch
2015/08/04 21:19:08
Done.
| |
| 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 ProfileCodeTrieNode* AppendKind(ProfileInfoKind kind, | |
| 1551 ProfileCodeTrieNode* current) { | |
| 1552 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { | |
| 1553 // Only emit if debug tags are requested. | |
| 1554 return current; | |
| 1555 } | |
| 1556 if (kind != info_kind_) { | |
| 1557 info_kind_ = kind; | |
| 1558 uword tag_map[] = { | |
| 1559 VMTag::kNoneCodeTagId, | |
| 1560 VMTag::kOptimizedCodeTagId, | |
| 1561 VMTag::kUnoptimizedCodeTagId, | |
| 1562 VMTag::kNativeCodeTagId, | |
| 1563 VMTag::kInlineStartCodeTagId, | |
| 1564 VMTag::kInlineEndCodeTagId, | |
| 1565 VMTag::kInvalidTagId | |
|
srdjan
2015/08/04 18:37:16
If the order must be the same as the other enums,
Cutch
2015/08/04 21:19:08
Done.
| |
| 1566 }; | |
| 1567 intptr_t tag_index = GetProfileCodeTagIndex(tag_map[kind]); | |
| 1568 ASSERT(tag_index >= 0); | |
| 1569 current = current->GetChild(tag_index); | |
| 1570 current->Tick(); | |
| 1571 } | |
| 1572 return current; | |
| 1573 } | |
| 1574 | |
| 1575 ProfileCodeTrieNode* AppendKind(const Code& code, | |
| 1576 ProfileCodeTrieNode* current) { | |
| 1577 if (code.IsNull()) { | |
| 1578 return AppendKind(kNone, current); | |
| 1579 } else if (code.is_optimized()) { | |
| 1580 return AppendKind(kOptimized, current); | |
| 1581 } else { | |
| 1582 return AppendKind(kUnoptimized, current); | |
| 1583 } | |
| 1584 } | |
| 1585 | |
| 1467 ProfileCodeTrieNode* AppendVMTags(uword vm_tag, | 1586 ProfileCodeTrieNode* AppendVMTags(uword vm_tag, |
| 1468 ProfileCodeTrieNode* current) { | 1587 ProfileCodeTrieNode* current) { |
| 1469 current = AppendVMTag(vm_tag, current); | 1588 current = AppendVMTag(vm_tag, current); |
| 1470 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); | 1589 current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); |
| 1471 return current; | 1590 return current; |
| 1472 } | 1591 } |
| 1473 | 1592 |
| 1474 ProfileCodeTrieNode* AppendTags(uword vm_tag, | 1593 ProfileCodeTrieNode* AppendTags(uword vm_tag, |
| 1475 uword user_tag, | 1594 uword user_tag, |
| 1476 ProfileCodeTrieNode* current) { | 1595 ProfileCodeTrieNode* current) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1493 (tag_order() == Profile::kVM)); | 1612 (tag_order() == Profile::kVM)); |
| 1494 current = AppendVMTags(vm_tag, current); | 1613 current = AppendVMTags(vm_tag, current); |
| 1495 // Only VM. | 1614 // Only VM. |
| 1496 if (tag_order() == Profile::kVM) { | 1615 if (tag_order() == Profile::kVM) { |
| 1497 return current; | 1616 return current; |
| 1498 } | 1617 } |
| 1499 return AppendUserTag(user_tag, current); | 1618 return AppendUserTag(user_tag, current); |
| 1500 } | 1619 } |
| 1501 | 1620 |
| 1502 // ProfileFunctionTrieNode | 1621 // ProfileFunctionTrieNode |
| 1622 void ResetKind() { | |
| 1623 info_kind_ = kNone; | |
| 1624 } | |
| 1625 | |
| 1626 ProfileFunctionTrieNode* AppendKind(ProfileInfoKind kind, | |
| 1627 ProfileFunctionTrieNode* current) { | |
| 1628 if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { | |
| 1629 // Only emit if debug tags are requested. | |
| 1630 return current; | |
| 1631 } | |
| 1632 if (kind != info_kind_) { | |
| 1633 info_kind_ = kind; | |
| 1634 uword tag_map[] = { | |
| 1635 VMTag::kNoneCodeTagId, | |
| 1636 VMTag::kOptimizedCodeTagId, | |
| 1637 VMTag::kUnoptimizedCodeTagId, | |
| 1638 VMTag::kNativeCodeTagId, | |
| 1639 VMTag::kInlineStartCodeTagId, | |
| 1640 VMTag::kInlineEndCodeTagId, | |
| 1641 VMTag::kInvalidTagId | |
| 1642 }; | |
|
srdjan
2015/08/04 18:37:16
This tag_map initialization is used repeatedly, ca
Cutch
2015/08/04 21:19:08
Done.
| |
| 1643 intptr_t tag_index = GetProfileFunctionTagIndex(tag_map[kind]); | |
| 1644 ASSERT(tag_index >= 0); | |
| 1645 current = current->GetChild(tag_index); | |
| 1646 current->Tick(); | |
| 1647 } | |
| 1648 return current; | |
| 1649 } | |
| 1650 | |
| 1651 ProfileFunctionTrieNode* AppendKind(const Code& code, | |
| 1652 ProfileFunctionTrieNode* current) { | |
| 1653 if (code.IsNull()) { | |
| 1654 return AppendKind(kNone, current); | |
| 1655 } else if (code.is_optimized()) { | |
| 1656 return AppendKind(kOptimized, current); | |
| 1657 } else { | |
| 1658 return AppendKind(kUnoptimized, current); | |
| 1659 } | |
| 1660 } | |
| 1661 | |
| 1503 ProfileFunctionTrieNode* AppendUserTag(uword user_tag, | 1662 ProfileFunctionTrieNode* AppendUserTag(uword user_tag, |
| 1504 ProfileFunctionTrieNode* current) { | 1663 ProfileFunctionTrieNode* current) { |
| 1505 intptr_t user_tag_index = GetProfileFunctionTagIndex(user_tag); | 1664 intptr_t user_tag_index = GetProfileFunctionTagIndex(user_tag); |
| 1506 if (user_tag_index >= 0) { | 1665 if (user_tag_index >= 0) { |
| 1507 current = current->GetChild(user_tag_index); | 1666 current = current->GetChild(user_tag_index); |
| 1508 current->Tick(); | 1667 current->Tick(); |
| 1509 } | 1668 } |
| 1510 return current; | 1669 return current; |
| 1511 } | 1670 } |
| 1512 | 1671 |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1776 Profile::TagOrder tag_order() const { | 1935 Profile::TagOrder tag_order() const { |
| 1777 return tag_order_; | 1936 return tag_order_; |
| 1778 } | 1937 } |
| 1779 | 1938 |
| 1780 bool vm_tags_emitted() const { | 1939 bool vm_tags_emitted() const { |
| 1781 return (tag_order_ == Profile::kUserVM) || | 1940 return (tag_order_ == Profile::kUserVM) || |
| 1782 (tag_order_ == Profile::kVMUser) || | 1941 (tag_order_ == Profile::kVMUser) || |
| 1783 (tag_order_ == Profile::kVM); | 1942 (tag_order_ == Profile::kVM); |
| 1784 } | 1943 } |
| 1785 | 1944 |
| 1945 bool TagsEnabled(intptr_t extra_tags_bits) { | |
| 1946 return (extra_tags_ & extra_tags_bits) != 0; | |
| 1947 } | |
| 1948 | |
| 1786 Isolate* isolate_; | 1949 Isolate* isolate_; |
| 1787 Isolate* vm_isolate_; | 1950 Isolate* vm_isolate_; |
| 1788 SampleFilter* filter_; | 1951 SampleFilter* filter_; |
| 1789 Profile::TagOrder tag_order_; | 1952 Profile::TagOrder tag_order_; |
| 1953 intptr_t extra_tags_; | |
| 1790 Profile* profile_; | 1954 Profile* profile_; |
| 1791 DeoptimizedCodeSet* deoptimized_code_; | 1955 DeoptimizedCodeSet* deoptimized_code_; |
| 1792 const Code& null_code_; | 1956 const Code& null_code_; |
| 1793 const Function& null_function_; | 1957 const Function& null_function_; |
| 1794 bool tick_functions_; | 1958 bool tick_functions_; |
| 1795 bool inclusive_tree_; | 1959 bool inclusive_tree_; |
| 1796 | 1960 |
| 1797 ProcessedSampleBuffer* samples_; | 1961 ProcessedSampleBuffer* samples_; |
| 1962 ProfileInfoKind info_kind_; | |
| 1798 }; | 1963 }; |
| 1799 | 1964 |
| 1800 | 1965 |
| 1801 Profile::Profile(Isolate* isolate) | 1966 Profile::Profile(Isolate* isolate) |
| 1802 : isolate_(isolate), | 1967 : isolate_(isolate), |
| 1803 live_code_(NULL), | 1968 live_code_(NULL), |
| 1804 dead_code_(NULL), | 1969 dead_code_(NULL), |
| 1805 tag_code_(NULL), | 1970 tag_code_(NULL), |
| 1806 functions_(NULL), | 1971 functions_(NULL), |
| 1807 dead_code_index_offset_(-1), | 1972 dead_code_index_offset_(-1), |
| 1808 tag_code_index_offset_(-1), | 1973 tag_code_index_offset_(-1), |
| 1809 min_time_(kMaxInt64), | 1974 min_time_(kMaxInt64), |
| 1810 max_time_(0) { | 1975 max_time_(0) { |
| 1811 ASSERT(isolate_ != NULL); | 1976 ASSERT(isolate_ != NULL); |
| 1812 for (intptr_t i = 0; i < kNumTrieKinds; i++) { | 1977 for (intptr_t i = 0; i < kNumTrieKinds; i++) { |
| 1813 roots_[i] = NULL; | 1978 roots_[i] = NULL; |
| 1814 } | 1979 } |
| 1815 } | 1980 } |
| 1816 | 1981 |
| 1817 | 1982 |
| 1818 void Profile::Build(SampleFilter* filter, TagOrder tag_order) { | 1983 void Profile::Build(SampleFilter* filter, |
| 1819 ProfileBuilder builder(isolate_, filter, tag_order, this); | 1984 TagOrder tag_order, |
| 1985 intptr_t extra_tags) { | |
| 1986 ProfileBuilder builder(isolate_, filter, tag_order, extra_tags, this); | |
| 1820 builder.Build(); | 1987 builder.Build(); |
| 1821 } | 1988 } |
| 1822 | 1989 |
| 1823 | 1990 |
| 1824 ProfileFunction* Profile::GetFunction(intptr_t index) { | 1991 ProfileFunction* Profile::GetFunction(intptr_t index) { |
| 1825 ASSERT(functions_ != NULL); | 1992 ASSERT(functions_ != NULL); |
| 1826 return functions_->At(index); | 1993 return functions_->At(index); |
| 1827 } | 1994 } |
| 1828 | 1995 |
| 1829 | 1996 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2012 | 2179 |
| 2013 intptr_t ProfileTrieWalker::SiblingCount() { | 2180 intptr_t ProfileTrieWalker::SiblingCount() { |
| 2014 ASSERT(parent_ != NULL); | 2181 ASSERT(parent_ != NULL); |
| 2015 return parent_->NumChildren(); | 2182 return parent_->NumChildren(); |
| 2016 } | 2183 } |
| 2017 | 2184 |
| 2018 | 2185 |
| 2019 void ProfilerService::PrintJSONImpl(Isolate* isolate, | 2186 void ProfilerService::PrintJSONImpl(Isolate* isolate, |
| 2020 JSONStream* stream, | 2187 JSONStream* stream, |
| 2021 Profile::TagOrder tag_order, | 2188 Profile::TagOrder tag_order, |
| 2189 intptr_t extra_tags, | |
| 2022 SampleFilter* filter) { | 2190 SampleFilter* filter) { |
| 2023 // Disable profile interrupts while processing the buffer. | 2191 // Disable profile interrupts while processing the buffer. |
| 2024 Profiler::EndExecution(isolate); | 2192 Profiler::EndExecution(isolate); |
| 2025 | 2193 |
| 2026 { | 2194 { |
| 2027 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); | 2195 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); |
| 2028 IsolateProfilerData* profiler_data = isolate->profiler_data(); | 2196 IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| 2029 if (profiler_data == NULL) { | 2197 if (profiler_data == NULL) { |
| 2030 stream->PrintError(kFeatureDisabled, NULL); | 2198 stream->PrintError(kFeatureDisabled, NULL); |
| 2031 return; | 2199 return; |
| 2032 } | 2200 } |
| 2033 } | 2201 } |
| 2034 | 2202 |
| 2035 { | 2203 { |
| 2036 StackZone zone(isolate); | 2204 StackZone zone(isolate); |
| 2037 HANDLESCOPE(isolate); | 2205 HANDLESCOPE(isolate); |
| 2038 Profile profile(isolate); | 2206 Profile profile(isolate); |
| 2039 profile.Build(filter, tag_order); | 2207 profile.Build(filter, tag_order, extra_tags); |
| 2040 profile.PrintJSON(stream); | 2208 profile.PrintJSON(stream); |
| 2041 } | 2209 } |
| 2042 | 2210 |
| 2043 // Enable profile interrupts. | 2211 // Enable profile interrupts. |
| 2044 Profiler::BeginExecution(isolate); | 2212 Profiler::BeginExecution(isolate); |
| 2045 } | 2213 } |
| 2046 | 2214 |
| 2047 | 2215 |
| 2048 class NoAllocationSampleFilter : public SampleFilter { | 2216 class NoAllocationSampleFilter : public SampleFilter { |
| 2049 public: | 2217 public: |
| 2050 explicit NoAllocationSampleFilter(Isolate* isolate) | 2218 explicit NoAllocationSampleFilter(Isolate* isolate) |
| 2051 : SampleFilter(isolate) { | 2219 : SampleFilter(isolate) { |
| 2052 } | 2220 } |
| 2053 | 2221 |
| 2054 bool FilterSample(Sample* sample) { | 2222 bool FilterSample(Sample* sample) { |
| 2055 return !sample->is_allocation_sample(); | 2223 return !sample->is_allocation_sample(); |
| 2056 } | 2224 } |
| 2057 }; | 2225 }; |
| 2058 | 2226 |
| 2059 | 2227 |
| 2060 void ProfilerService::PrintJSON(JSONStream* stream, | 2228 void ProfilerService::PrintJSON(JSONStream* stream, |
| 2061 Profile::TagOrder tag_order) { | 2229 Profile::TagOrder tag_order, |
| 2230 intptr_t extra_tags) { | |
| 2062 Isolate* isolate = Isolate::Current(); | 2231 Isolate* isolate = Isolate::Current(); |
| 2063 NoAllocationSampleFilter filter(isolate); | 2232 NoAllocationSampleFilter filter(isolate); |
| 2064 PrintJSONImpl(isolate, stream, tag_order, &filter); | 2233 PrintJSONImpl(isolate, stream, tag_order, extra_tags, &filter); |
| 2065 } | 2234 } |
| 2066 | 2235 |
| 2067 | 2236 |
| 2068 class ClassAllocationSampleFilter : public SampleFilter { | 2237 class ClassAllocationSampleFilter : public SampleFilter { |
| 2069 public: | 2238 public: |
| 2070 ClassAllocationSampleFilter(Isolate* isolate, const Class& cls) | 2239 ClassAllocationSampleFilter(Isolate* isolate, const Class& cls) |
| 2071 : SampleFilter(isolate), | 2240 : SampleFilter(isolate), |
| 2072 cls_(Class::Handle(cls.raw())) { | 2241 cls_(Class::Handle(cls.raw())) { |
| 2073 ASSERT(!cls_.IsNull()); | 2242 ASSERT(!cls_.IsNull()); |
| 2074 } | 2243 } |
| 2075 | 2244 |
| 2076 bool FilterSample(Sample* sample) { | 2245 bool FilterSample(Sample* sample) { |
| 2077 return sample->is_allocation_sample() && | 2246 return sample->is_allocation_sample() && |
| 2078 (sample->allocation_cid() == cls_.id()); | 2247 (sample->allocation_cid() == cls_.id()); |
| 2079 } | 2248 } |
| 2080 | 2249 |
| 2081 private: | 2250 private: |
| 2082 const Class& cls_; | 2251 const Class& cls_; |
| 2083 }; | 2252 }; |
| 2084 | 2253 |
| 2085 | 2254 |
| 2086 void ProfilerService::PrintAllocationJSON(JSONStream* stream, | 2255 void ProfilerService::PrintAllocationJSON(JSONStream* stream, |
| 2087 Profile::TagOrder tag_order, | 2256 Profile::TagOrder tag_order, |
| 2088 const Class& cls) { | 2257 const Class& cls) { |
| 2089 Isolate* isolate = Isolate::Current(); | 2258 Isolate* isolate = Isolate::Current(); |
| 2090 ClassAllocationSampleFilter filter(isolate, cls); | 2259 ClassAllocationSampleFilter filter(isolate, cls); |
| 2091 PrintJSONImpl(isolate, stream, tag_order, &filter); | 2260 PrintJSONImpl(isolate, stream, tag_order, 0, &filter); |
| 2092 } | 2261 } |
| 2093 | 2262 |
| 2094 | 2263 |
| 2095 void ProfilerService::ClearSamples() { | 2264 void ProfilerService::ClearSamples() { |
| 2096 Isolate* isolate = Isolate::Current(); | 2265 Isolate* isolate = Isolate::Current(); |
| 2097 | 2266 |
| 2098 // Disable profile interrupts while processing the buffer. | 2267 // Disable profile interrupts while processing the buffer. |
| 2099 Profiler::EndExecution(isolate); | 2268 Profiler::EndExecution(isolate); |
| 2100 | 2269 |
| 2101 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); | 2270 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); |
| 2102 IsolateProfilerData* profiler_data = isolate->profiler_data(); | 2271 IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| 2103 if (profiler_data == NULL) { | 2272 if (profiler_data == NULL) { |
| 2104 return; | 2273 return; |
| 2105 } | 2274 } |
| 2106 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); | 2275 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); |
| 2107 ASSERT(sample_buffer != NULL); | 2276 ASSERT(sample_buffer != NULL); |
| 2108 | 2277 |
| 2109 ClearProfileVisitor clear_profile(isolate); | 2278 ClearProfileVisitor clear_profile(isolate); |
| 2110 sample_buffer->VisitSamples(&clear_profile); | 2279 sample_buffer->VisitSamples(&clear_profile); |
| 2111 | 2280 |
| 2112 // Enable profile interrupts. | 2281 // Enable profile interrupts. |
| 2113 Profiler::BeginExecution(isolate); | 2282 Profiler::BeginExecution(isolate); |
| 2114 } | 2283 } |
| 2115 | 2284 |
| 2116 } // namespace dart | 2285 } // namespace dart |
| OLD | NEW |