| 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/log.h" |
| 8 #include "vm/native_symbol.h" | 9 #include "vm/native_symbol.h" |
| 9 #include "vm/object.h" | 10 #include "vm/object.h" |
| 10 #include "vm/os.h" | 11 #include "vm/os.h" |
| 11 #include "vm/profiler.h" | 12 #include "vm/profiler.h" |
| 12 #include "vm/reusable_handles.h" | 13 #include "vm/reusable_handles.h" |
| 13 #include "vm/scope_timer.h" | 14 #include "vm/scope_timer.h" |
| 14 | 15 |
| 15 namespace dart { | 16 namespace dart { |
| 16 | 17 |
| 17 DECLARE_FLAG(int, max_profile_depth); | 18 DECLARE_FLAG(int, max_profile_depth); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 return size; | 83 return size; |
| 83 } | 84 } |
| 84 | 85 |
| 85 // Array holding code that is being kept around only for the profiler. | 86 // Array holding code that is being kept around only for the profiler. |
| 86 const GrowableObjectArray& previous_; | 87 const GrowableObjectArray& previous_; |
| 87 // Array holding code that should continue to be kept around for the profiler. | 88 // Array holding code that should continue to be kept around for the profiler. |
| 88 const GrowableObjectArray& current_; | 89 const GrowableObjectArray& current_; |
| 89 }; | 90 }; |
| 90 | 91 |
| 91 | 92 |
| 93 ProfileFunctionSourcePosition::ProfileFunctionSourcePosition( |
| 94 TokenPosition token_pos) |
| 95 : token_pos_(token_pos), |
| 96 exclusive_ticks_(0), |
| 97 inclusive_ticks_(0) { |
| 98 } |
| 99 |
| 100 |
| 101 void ProfileFunctionSourcePosition::Tick(bool exclusive) { |
| 102 if (exclusive) { |
| 103 exclusive_ticks_++; |
| 104 } else { |
| 105 inclusive_ticks_++; |
| 106 } |
| 107 } |
| 108 |
| 109 |
| 92 ProfileFunction::ProfileFunction(Kind kind, | 110 ProfileFunction::ProfileFunction(Kind kind, |
| 93 const char* name, | 111 const char* name, |
| 94 const Function& function, | 112 const Function& function, |
| 95 const intptr_t table_index) | 113 const intptr_t table_index) |
| 96 : kind_(kind), | 114 : kind_(kind), |
| 97 name_(name), | 115 name_(name), |
| 98 function_(Function::ZoneHandle(function.raw())), | 116 function_(Function::ZoneHandle(function.raw())), |
| 99 table_index_(table_index), | 117 table_index_(table_index), |
| 100 profile_codes_(0), | 118 profile_codes_(0), |
| 119 source_position_ticks_(0), |
| 101 exclusive_ticks_(0), | 120 exclusive_ticks_(0), |
| 102 inclusive_ticks_(0), | 121 inclusive_ticks_(0), |
| 103 inclusive_serial_(-1) { | 122 inclusive_serial_(-1) { |
| 104 ASSERT((kind_ != kDartFunction) || !function_.IsNull()); | 123 ASSERT((kind_ != kDartFunction) || !function_.IsNull()); |
| 105 ASSERT((kind_ != kDartFunction) || (table_index_ >= 0)); | 124 ASSERT((kind_ != kDartFunction) || (table_index_ >= 0)); |
| 106 ASSERT(profile_codes_.length() == 0); | 125 ASSERT(profile_codes_.length() == 0); |
| 107 } | 126 } |
| 108 | 127 |
| 109 | 128 |
| 110 const char* ProfileFunction::Name() const { | 129 const char* ProfileFunction::Name() const { |
| 111 if (name_ != NULL) { | 130 if (name_ != NULL) { |
| 112 return name_; | 131 return name_; |
| 113 } | 132 } |
| 114 ASSERT(!function_.IsNull()); | 133 ASSERT(!function_.IsNull()); |
| 115 const String& func_name = | 134 const String& func_name = |
| 116 String::Handle(function_.QualifiedUserVisibleName()); | 135 String::Handle(function_.QualifiedUserVisibleName()); |
| 117 return func_name.ToCString(); | 136 return func_name.ToCString(); |
| 118 } | 137 } |
| 119 | 138 |
| 120 void ProfileFunction::Tick(bool exclusive, intptr_t inclusive_serial) { | 139 |
| 140 void ProfileFunction::Tick(bool exclusive, |
| 141 intptr_t inclusive_serial, |
| 142 TokenPosition token_position) { |
| 121 if (exclusive) { | 143 if (exclusive) { |
| 122 exclusive_ticks_++; | 144 exclusive_ticks_++; |
| 145 TickSourcePosition(token_position, exclusive); |
| 123 } | 146 } |
| 124 // Fall through and tick inclusive count too. | 147 // Fall through and tick inclusive count too. |
| 125 if (inclusive_serial_ == inclusive_serial) { | 148 if (inclusive_serial_ == inclusive_serial) { |
| 126 // Already ticked. | 149 // Already ticked. |
| 127 return; | 150 return; |
| 128 } | 151 } |
| 129 inclusive_serial_ = inclusive_serial; | 152 inclusive_serial_ = inclusive_serial; |
| 130 inclusive_ticks_++; | 153 inclusive_ticks_++; |
| 154 TickSourcePosition(token_position, false); |
| 131 } | 155 } |
| 132 | 156 |
| 133 | 157 |
| 158 void ProfileFunction::TickSourcePosition(TokenPosition token_position, |
| 159 bool exclusive) { |
| 160 for (intptr_t i = 0; i < source_position_ticks_.length(); i++) { |
| 161 ProfileFunctionSourcePosition& position = source_position_ticks_[i]; |
| 162 if (position.token_pos() == token_position) { |
| 163 // Found existing position, tick it. |
| 164 position.Tick(exclusive); |
| 165 return; |
| 166 } |
| 167 } |
| 168 // Add new one. |
| 169 ProfileFunctionSourcePosition pfsp(token_position); |
| 170 pfsp.Tick(exclusive); |
| 171 source_position_ticks_.Add(pfsp); |
| 172 } |
| 173 |
| 174 |
| 134 const char* ProfileFunction::KindToCString(Kind kind) { | 175 const char* ProfileFunction::KindToCString(Kind kind) { |
| 135 switch (kind) { | 176 switch (kind) { |
| 136 case kDartFunction: | 177 case kDartFunction: |
| 137 return "Dart"; | 178 return "Dart"; |
| 138 case kNativeFunction: | 179 case kNativeFunction: |
| 139 return "Native"; | 180 return "Native"; |
| 140 case kTagFunction: | 181 case kTagFunction: |
| 141 return "Tag"; | 182 return "Tag"; |
| 142 case kStubFunction: | 183 case kStubFunction: |
| 143 return "Stub"; | 184 return "Stub"; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 void ProfileFunction::AddProfileCode(intptr_t code_table_index) { | 223 void ProfileFunction::AddProfileCode(intptr_t code_table_index) { |
| 183 for (intptr_t i = 0; i < profile_codes_.length(); i++) { | 224 for (intptr_t i = 0; i < profile_codes_.length(); i++) { |
| 184 if (profile_codes_[i] == code_table_index) { | 225 if (profile_codes_[i] == code_table_index) { |
| 185 return; | 226 return; |
| 186 } | 227 } |
| 187 } | 228 } |
| 188 profile_codes_.Add(code_table_index); | 229 profile_codes_.Add(code_table_index); |
| 189 } | 230 } |
| 190 | 231 |
| 191 | 232 |
| 233 bool ProfileFunction::GetSinglePosition(ProfileFunctionSourcePosition* pfsp) { |
| 234 if (pfsp == NULL) { |
| 235 return false; |
| 236 } |
| 237 if (source_position_ticks_.length() != 1) { |
| 238 return false; |
| 239 } |
| 240 *pfsp = source_position_ticks_[0]; |
| 241 return true; |
| 242 } |
| 243 |
| 244 |
| 192 ProfileCodeAddress::ProfileCodeAddress(uword pc) | 245 ProfileCodeAddress::ProfileCodeAddress(uword pc) |
| 193 : pc_(pc), | 246 : pc_(pc), |
| 194 exclusive_ticks_(0), | 247 exclusive_ticks_(0), |
| 195 inclusive_ticks_(0) { | 248 inclusive_ticks_(0) { |
| 196 } | 249 } |
| 197 | 250 |
| 198 | 251 |
| 199 void ProfileCodeAddress::Tick(bool exclusive) { | 252 void ProfileCodeAddress::Tick(bool exclusive) { |
| 200 if (exclusive) { | 253 if (exclusive) { |
| 201 exclusive_ticks_++; | 254 exclusive_ticks_++; |
| (...skipping 1179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1381 intptr_t frame_index) { | 1434 intptr_t frame_index) { |
| 1382 const uword pc = sample->At(frame_index); | 1435 const uword pc = sample->At(frame_index); |
| 1383 ProfileCode* profile_code = GetProfileCode(pc, | 1436 ProfileCode* profile_code = GetProfileCode(pc, |
| 1384 sample->timestamp()); | 1437 sample->timestamp()); |
| 1385 ProfileFunction* function = profile_code->function(); | 1438 ProfileFunction* function = profile_code->function(); |
| 1386 ASSERT(function != NULL); | 1439 ASSERT(function != NULL); |
| 1387 const intptr_t code_index = profile_code->code_table_index(); | 1440 const intptr_t code_index = profile_code->code_table_index(); |
| 1388 ASSERT(profile_code != NULL); | 1441 ASSERT(profile_code != NULL); |
| 1389 const Code& code = Code::ZoneHandle(profile_code->code()); | 1442 const Code& code = Code::ZoneHandle(profile_code->code()); |
| 1390 GrowableArray<Function*> inlined_functions; | 1443 GrowableArray<Function*> inlined_functions; |
| 1444 GrowableArray<TokenPosition> inlined_token_positions; |
| 1445 TokenPosition token_position = TokenPosition::kNoSource; |
| 1391 if (!code.IsNull()) { | 1446 if (!code.IsNull()) { |
| 1392 intptr_t offset = pc - code.EntryPoint(); | 1447 intptr_t offset = pc - code.EntryPoint(); |
| 1393 if (frame_index != 0) { | 1448 if (frame_index != 0) { |
| 1394 // The PC of frames below the top frame is a call's return address, | 1449 // The PC of frames below the top frame is a call's return address, |
| 1395 // which can belong to a different inlining interval than the call. | 1450 // which can belong to a different inlining interval than the call. |
| 1396 offset--; | 1451 offset--; |
| 1452 } else if (sample->IsAllocationSample()) { |
| 1453 // Allocation samples skip the top frame, so the top frame's pc is |
| 1454 // also a call's return address. |
| 1455 offset--; |
| 1397 } | 1456 } |
| 1398 code.GetInlinedFunctionsAt(offset, &inlined_functions); | 1457 code.GetInlinedFunctionsAt(offset, |
| 1458 &inlined_functions, |
| 1459 &inlined_token_positions); |
| 1460 token_position = code.GetTokenPositionAt(offset); |
| 1461 if (inlined_functions.length() > 0) { |
| 1462 // The inlined token position table does not include the token position |
| 1463 // of the final call. Insert it at the beginning because the table. |
| 1464 // is reversed. |
| 1465 inlined_token_positions.InsertAt(0, token_position); |
| 1466 } |
| 1467 ASSERT(inlined_functions.length() <= inlined_token_positions.length()); |
| 1468 if (FLAG_trace_profiler) { |
| 1469 for (intptr_t i = 0; i < inlined_functions.length(); i++) { |
| 1470 const String& name = |
| 1471 String::Handle(inlined_functions[i]->QualifiedScrubbedName()); |
| 1472 THR_Print("InlinedFunction[%" Pd "] = {%s, %s}\n", |
| 1473 i, |
| 1474 name.ToCString(), |
| 1475 inlined_token_positions[i].ToCString()); |
| 1476 } |
| 1477 } |
| 1399 } | 1478 } |
| 1400 if (code.IsNull() || (inlined_functions.length() == 0)) { | 1479 if (code.IsNull() || (inlined_functions.length() == 0)) { |
| 1401 // No inlined functions. | 1480 // No inlined functions. |
| 1402 if (inclusive_tree_) { | 1481 if (inclusive_tree_) { |
| 1403 current = AppendKind(code, current); | 1482 current = AppendKind(code, current); |
| 1404 } | 1483 } |
| 1405 current = ProcessFunction(current, | 1484 current = ProcessFunction(current, |
| 1406 sample_index, | 1485 sample_index, |
| 1407 sample, | 1486 sample, |
| 1408 frame_index, | 1487 frame_index, |
| 1409 function, | 1488 function, |
| 1489 token_position, |
| 1410 code_index); | 1490 code_index); |
| 1411 if (!inclusive_tree_) { | 1491 if (!inclusive_tree_) { |
| 1412 current = AppendKind(code, current); | 1492 current = AppendKind(code, current); |
| 1413 } | 1493 } |
| 1414 return current; | 1494 return current; |
| 1415 } | 1495 } |
| 1416 | 1496 |
| 1417 ASSERT(code.is_optimized()); | 1497 ASSERT(code.is_optimized()); |
| 1418 | 1498 |
| 1419 if (inclusive_tree_) { | 1499 if (inclusive_tree_) { |
| 1420 for (intptr_t i = inlined_functions.length() - 1; i >= 0; i--) { | 1500 for (intptr_t i = inlined_functions.length() - 1; i >= 0; i--) { |
| 1421 Function* inlined_function = inlined_functions[i]; | 1501 Function* inlined_function = inlined_functions[i]; |
| 1422 ASSERT(inlined_function != NULL); | 1502 ASSERT(inlined_function != NULL); |
| 1423 ASSERT(!inlined_function->IsNull()); | 1503 ASSERT(!inlined_function->IsNull()); |
| 1504 TokenPosition inlined_token_position = inlined_token_positions[i]; |
| 1424 const bool inliner = i == (inlined_functions.length() - 1); | 1505 const bool inliner = i == (inlined_functions.length() - 1); |
| 1425 if (inliner) { | 1506 if (inliner) { |
| 1426 current = AppendKind(code, current); | 1507 current = AppendKind(code, current); |
| 1427 } | 1508 } |
| 1428 current = ProcessInlinedFunction(current, | 1509 current = ProcessInlinedFunction(current, |
| 1429 sample_index, | 1510 sample_index, |
| 1430 sample, | 1511 sample, |
| 1431 frame_index, | 1512 frame_index, |
| 1432 inlined_function, | 1513 inlined_function, |
| 1514 inlined_token_position, |
| 1433 code_index); | 1515 code_index); |
| 1434 if (inliner) { | 1516 if (inliner) { |
| 1435 current = AppendKind(kInlineStart, current); | 1517 current = AppendKind(kInlineStart, current); |
| 1436 } | 1518 } |
| 1437 } | 1519 } |
| 1438 current = AppendKind(kInlineFinish, current); | 1520 current = AppendKind(kInlineFinish, current); |
| 1439 } else { | 1521 } else { |
| 1440 // Append the inlined children. | 1522 // Append the inlined children. |
| 1441 current = AppendKind(kInlineFinish, current); | 1523 current = AppendKind(kInlineFinish, current); |
| 1442 for (intptr_t i = 0; i < inlined_functions.length(); i++) { | 1524 for (intptr_t i = 0; i < inlined_functions.length(); i++) { |
| 1443 Function* inlined_function = inlined_functions[i]; | 1525 Function* inlined_function = inlined_functions[i]; |
| 1444 ASSERT(inlined_function != NULL); | 1526 ASSERT(inlined_function != NULL); |
| 1445 ASSERT(!inlined_function->IsNull()); | 1527 ASSERT(!inlined_function->IsNull()); |
| 1528 TokenPosition inlined_token_position = inlined_token_positions[i]; |
| 1446 const bool inliner = i == (inlined_functions.length() - 1); | 1529 const bool inliner = i == (inlined_functions.length() - 1); |
| 1447 if (inliner) { | 1530 if (inliner) { |
| 1448 current = AppendKind(kInlineStart, current); | 1531 current = AppendKind(kInlineStart, current); |
| 1449 } | 1532 } |
| 1450 current = ProcessInlinedFunction(current, | 1533 current = ProcessInlinedFunction(current, |
| 1451 sample_index, | 1534 sample_index, |
| 1452 sample, | 1535 sample, |
| 1453 frame_index + i, | 1536 frame_index + i, |
| 1454 inlined_function, | 1537 inlined_function, |
| 1538 inlined_token_position, |
| 1455 code_index); | 1539 code_index); |
| 1456 if (inliner) { | 1540 if (inliner) { |
| 1457 current = AppendKind(code, current); | 1541 current = AppendKind(code, current); |
| 1458 } | 1542 } |
| 1459 } | 1543 } |
| 1460 } | 1544 } |
| 1461 | 1545 |
| 1462 return current; | 1546 return current; |
| 1463 } | 1547 } |
| 1464 | 1548 |
| 1465 ProfileFunctionTrieNode* ProcessInlinedFunction( | 1549 ProfileFunctionTrieNode* ProcessInlinedFunction( |
| 1466 ProfileFunctionTrieNode* current, | 1550 ProfileFunctionTrieNode* current, |
| 1467 intptr_t sample_index, | 1551 intptr_t sample_index, |
| 1468 ProcessedSample* sample, | 1552 ProcessedSample* sample, |
| 1469 intptr_t frame_index, | 1553 intptr_t frame_index, |
| 1470 Function* inlined_function, | 1554 Function* inlined_function, |
| 1555 TokenPosition inlined_token_position, |
| 1471 intptr_t code_index) { | 1556 intptr_t code_index) { |
| 1472 ProfileFunctionTable* function_table = profile_->functions_; | 1557 ProfileFunctionTable* function_table = profile_->functions_; |
| 1473 ProfileFunction* function = function_table->LookupOrAdd(*inlined_function); | 1558 ProfileFunction* function = function_table->LookupOrAdd(*inlined_function); |
| 1474 ASSERT(function != NULL); | 1559 ASSERT(function != NULL); |
| 1475 return ProcessFunction(current, | 1560 return ProcessFunction(current, |
| 1476 sample_index, | 1561 sample_index, |
| 1477 sample, | 1562 sample, |
| 1478 frame_index, | 1563 frame_index, |
| 1479 function, | 1564 function, |
| 1565 inlined_token_position, |
| 1480 code_index); | 1566 code_index); |
| 1481 } | 1567 } |
| 1482 | 1568 |
| 1483 bool ShouldTickNode(ProcessedSample* sample, intptr_t frame_index) { | 1569 bool ShouldTickNode(ProcessedSample* sample, intptr_t frame_index) { |
| 1484 if (frame_index != 0) { | 1570 if (frame_index != 0) { |
| 1485 return true; | 1571 return true; |
| 1486 } | 1572 } |
| 1487 // Only tick the first frame's node, if we are executing OR | 1573 // Only tick the first frame's node, if we are executing OR |
| 1488 // vm tags have been emitted. | 1574 // vm tags have been emitted. |
| 1489 return IsExecutingFrame(sample, frame_index) || vm_tags_emitted(); | 1575 return IsExecutingFrame(sample, frame_index) || vm_tags_emitted(); |
| 1490 } | 1576 } |
| 1491 | 1577 |
| 1492 ProfileFunctionTrieNode* ProcessFunction(ProfileFunctionTrieNode* current, | 1578 ProfileFunctionTrieNode* ProcessFunction(ProfileFunctionTrieNode* current, |
| 1493 intptr_t sample_index, | 1579 intptr_t sample_index, |
| 1494 ProcessedSample* sample, | 1580 ProcessedSample* sample, |
| 1495 intptr_t frame_index, | 1581 intptr_t frame_index, |
| 1496 ProfileFunction* function, | 1582 ProfileFunction* function, |
| 1583 TokenPosition token_position, |
| 1497 intptr_t code_index) { | 1584 intptr_t code_index) { |
| 1585 if (FLAG_trace_profiler) { |
| 1586 THR_Print("S[%" Pd "]F[%" Pd "] %s %s\n", |
| 1587 sample_index, |
| 1588 frame_index, |
| 1589 function->Name(), token_position.ToCString()); |
| 1590 } |
| 1498 if (tick_functions_) { | 1591 if (tick_functions_) { |
| 1499 function->Tick(IsExecutingFrame(sample, frame_index), sample_index); | 1592 function->Tick(IsExecutingFrame(sample, frame_index), |
| 1593 sample_index, |
| 1594 token_position); |
| 1500 } | 1595 } |
| 1501 function->AddProfileCode(code_index); | 1596 function->AddProfileCode(code_index); |
| 1502 current = current->GetChild(function->table_index()); | 1597 current = current->GetChild(function->table_index()); |
| 1503 if (ShouldTickNode(sample, frame_index)) { | 1598 if (ShouldTickNode(sample, frame_index)) { |
| 1504 current->Tick(); | 1599 current->Tick(); |
| 1505 } | 1600 } |
| 1506 current->AddCodeObjectIndex(code_index); | 1601 current->AddCodeObjectIndex(code_index); |
| 1507 return current; | 1602 return current; |
| 1508 } | 1603 } |
| 1509 | 1604 |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2237 ProfileCode* code = profile_->GetCode(current_->table_index()); | 2332 ProfileCode* code = profile_->GetCode(current_->table_index()); |
| 2238 return code->exclusive_ticks(); | 2333 return code->exclusive_ticks(); |
| 2239 } else { | 2334 } else { |
| 2240 ProfileFunction* func = profile_->GetFunction(current_->table_index()); | 2335 ProfileFunction* func = profile_->GetFunction(current_->table_index()); |
| 2241 return func->exclusive_ticks(); | 2336 return func->exclusive_ticks(); |
| 2242 } | 2337 } |
| 2243 UNREACHABLE(); | 2338 UNREACHABLE(); |
| 2244 } | 2339 } |
| 2245 | 2340 |
| 2246 | 2341 |
| 2342 const char* ProfileTrieWalker::CurrentToken() { |
| 2343 if (current_ == NULL) { |
| 2344 return NULL; |
| 2345 } |
| 2346 if (code_trie_) { |
| 2347 return NULL; |
| 2348 } |
| 2349 ProfileFunction* func = profile_->GetFunction(current_->table_index()); |
| 2350 const Function& function = Function::Handle(func->function()); |
| 2351 if (function.IsNull()) { |
| 2352 // No function. |
| 2353 return NULL; |
| 2354 } |
| 2355 const Script& script = Script::Handle(function.script()); |
| 2356 if (script.IsNull()) { |
| 2357 // No script. |
| 2358 return NULL; |
| 2359 } |
| 2360 const TokenStream& token_stream = TokenStream::Handle(script.tokens()); |
| 2361 if (token_stream.IsNull()) { |
| 2362 // No token position. |
| 2363 return NULL; |
| 2364 } |
| 2365 ProfileFunctionSourcePosition pfsp(TokenPosition::kNoSource); |
| 2366 if (!func->GetSinglePosition(&pfsp)) { |
| 2367 // Not exactly one source position. |
| 2368 return NULL; |
| 2369 } |
| 2370 TokenPosition token_pos = pfsp.token_pos(); |
| 2371 if (!token_pos.IsReal() && !token_pos.IsSynthetic()) { |
| 2372 // Not a location in a script. |
| 2373 return NULL; |
| 2374 } |
| 2375 if (token_pos.IsSynthetic()) { |
| 2376 token_pos = token_pos.FromSynthetic(); |
| 2377 } |
| 2378 TokenStream::Iterator iterator(token_stream, token_pos); |
| 2379 const String& str = String::Handle(iterator.CurrentLiteral()); |
| 2380 if (str.IsNull()) { |
| 2381 return NULL; |
| 2382 } |
| 2383 return str.ToCString(); |
| 2384 } |
| 2385 |
| 2247 bool ProfileTrieWalker::Down() { | 2386 bool ProfileTrieWalker::Down() { |
| 2248 if ((current_ == NULL) || (current_->NumChildren() == 0)) { | 2387 if ((current_ == NULL) || (current_->NumChildren() == 0)) { |
| 2249 return false; | 2388 return false; |
| 2250 } | 2389 } |
| 2251 parent_ = current_; | 2390 parent_ = current_; |
| 2252 current_ = current_->At(0); | 2391 current_ = current_->At(0); |
| 2253 return true; | 2392 return true; |
| 2254 } | 2393 } |
| 2255 | 2394 |
| 2256 | 2395 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2403 // Disable thread interrupts while processing the buffer. | 2542 // Disable thread interrupts while processing the buffer. |
| 2404 DisableThreadInterruptsScope dtis(thread); | 2543 DisableThreadInterruptsScope dtis(thread); |
| 2405 | 2544 |
| 2406 ClearProfileVisitor clear_profile(isolate); | 2545 ClearProfileVisitor clear_profile(isolate); |
| 2407 sample_buffer->VisitSamples(&clear_profile); | 2546 sample_buffer->VisitSamples(&clear_profile); |
| 2408 } | 2547 } |
| 2409 | 2548 |
| 2410 #endif // !PRODUCT | 2549 #endif // !PRODUCT |
| 2411 | 2550 |
| 2412 } // namespace dart | 2551 } // namespace dart |
| OLD | NEW |