Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: runtime/vm/profiler.cc

Issue 227433004: Add runtime and native entry tags (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 "platform/utils.h" 5 #include "platform/utils.h"
6 6
7 #include "vm/allocation.h" 7 #include "vm/allocation.h"
8 #include "vm/atomic.h" 8 #include "vm/atomic.h"
9 #include "vm/code_patcher.h" 9 #include "vm/code_patcher.h"
10 #include "vm/isolate.h" 10 #include "vm/isolate.h"
(...skipping 17 matching lines...) Expand all
28 #endif 28 #endif
29 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates."); 29 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
30 DEFINE_FLAG(charp, profile_dir, NULL, 30 DEFINE_FLAG(charp, profile_dir, NULL,
31 "Enable writing profile data into specified directory."); 31 "Enable writing profile data into specified directory.");
32 DEFINE_FLAG(int, profile_period, 1000, 32 DEFINE_FLAG(int, profile_period, 1000,
33 "Time between profiler samples in microseconds. Minimum 250."); 33 "Time between profiler samples in microseconds. Minimum 250.");
34 DEFINE_FLAG(int, profile_depth, 8, 34 DEFINE_FLAG(int, profile_depth, 8,
35 "Maximum number stack frames walked. Minimum 1. Maximum 255."); 35 "Maximum number stack frames walked. Minimum 1. Maximum 255.");
36 DEFINE_FLAG(bool, profile_verify_stack_walk, false, 36 DEFINE_FLAG(bool, profile_verify_stack_walk, false,
37 "Verify instruction addresses while walking the stack."); 37 "Verify instruction addresses while walking the stack.");
38 DEFINE_FLAG(bool, profile_native_stack, true,
39 "Use native stack in profiler.");
38 40
39 bool Profiler::initialized_ = false; 41 bool Profiler::initialized_ = false;
40 SampleBuffer* Profiler::sample_buffer_ = NULL; 42 SampleBuffer* Profiler::sample_buffer_ = NULL;
41 43
42 void Profiler::InitOnce() { 44 void Profiler::InitOnce() {
43 // Place some sane restrictions on user controlled flags. 45 // Place some sane restrictions on user controlled flags.
44 SetSamplePeriod(FLAG_profile_period); 46 SetSamplePeriod(FLAG_profile_period);
45 SetSampleDepth(FLAG_profile_depth); 47 SetSampleDepth(FLAG_profile_depth);
46 if (!FLAG_profile) { 48 if (!FLAG_profile) {
47 return; 49 return;
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 921
920 void VisitSample(Sample* sample) { 922 void VisitSample(Sample* sample) {
921 int64_t timestamp = sample->timestamp(); 923 int64_t timestamp = sample->timestamp();
922 if (timestamp > max_time_) { 924 if (timestamp > max_time_) {
923 max_time_ = timestamp; 925 max_time_ = timestamp;
924 } 926 }
925 if (timestamp < min_time_) { 927 if (timestamp < min_time_) {
926 min_time_ = timestamp; 928 min_time_ = timestamp;
927 } 929 }
928 // Make sure VM tag is created. 930 // Make sure VM tag is created.
931 if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
932 CreateTag(VMTag::kNativeTagId);
933 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
934 CreateTag(VMTag::kRuntimeTagId);
935 }
929 CreateTag(sample->vm_tag()); 936 CreateTag(sample->vm_tag());
930 // Exclusive tick for bottom frame. 937 // Exclusive tick for bottom frame.
931 Tick(sample->At(0), true, timestamp); 938 Tick(sample->At(0), true, timestamp);
932 // Inclusive tick for all frames. 939 // Inclusive tick for all frames.
933 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 940 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
934 if (sample->At(i) == 0) { 941 if (sample->At(i) == 0) {
935 break; 942 break;
936 } 943 }
937 frames_++; 944 frames_++;
938 Tick(sample->At(i), false, timestamp); 945 Tick(sample->At(i), false, timestamp);
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 root_ = new CodeRegionTrieNode(tag_code_table_offset_ + root_index); 1101 root_ = new CodeRegionTrieNode(tag_code_table_offset_ + root_index);
1095 // Use tags by default. 1102 // Use tags by default.
1096 set_use_tags(true); 1103 set_use_tags(true);
1097 } 1104 }
1098 1105
1099 void VisitSample(Sample* sample) { 1106 void VisitSample(Sample* sample) {
1100 // Give the root a tick. 1107 // Give the root a tick.
1101 root_->Tick(); 1108 root_->Tick();
1102 CodeRegionTrieNode* current = root_; 1109 CodeRegionTrieNode* current = root_;
1103 if (use_tags()) { 1110 if (use_tags()) {
1111 if (VMTag::IsNativeEntryTag(sample->vm_tag())) {
1112 // Insert a dummy kNativeTagId node.
1113 intptr_t tag_index = FindTagIndex(VMTag::kNativeTagId);
1114 current = current->GetChild(tag_index);
1115 // Give the tag a tick.
1116 current->Tick();
1117 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) {
1118 // Insert a dummy kRuntimeTagId node.
1119 intptr_t tag_index = FindTagIndex(VMTag::kRuntimeTagId);
1120 current = current->GetChild(tag_index);
1121 // Give the tag a tick.
1122 current->Tick();
1123 }
1104 intptr_t tag_index = FindTagIndex(sample->vm_tag()); 1124 intptr_t tag_index = FindTagIndex(sample->vm_tag());
1105 current = current->GetChild(tag_index); 1125 current = current->GetChild(tag_index);
1106 // Give the tag a tick. 1126 // Give the tag a tick.
1107 current->Tick(); 1127 current->Tick();
1108 } 1128 }
1109 // Walk the sampled PCs. 1129 // Walk the sampled PCs.
1110 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 1130 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
1111 if (sample->At(i) == 0) { 1131 if (sample->At(i) == 0) {
1112 break; 1132 break;
1113 } 1133 }
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
1399 1419
1400 1420
1401 Sample* SampleBuffer::ReserveSample() { 1421 Sample* SampleBuffer::ReserveSample() {
1402 ASSERT(samples_ != NULL); 1422 ASSERT(samples_ != NULL);
1403 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_); 1423 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
1404 // Map back into sample buffer range. 1424 // Map back into sample buffer range.
1405 cursor = cursor % capacity_; 1425 cursor = cursor % capacity_;
1406 return At(cursor); 1426 return At(cursor);
1407 } 1427 }
1408 1428
1429 class ProfilerDartStackWalker : public ValueObject {
1430 public:
1431 explicit ProfilerDartStackWalker(Sample* sample)
1432 : sample_(sample),
1433 frame_iterator_() {
1434 ASSERT(sample_ != NULL);
1435 }
1436
1437 ProfilerDartStackWalker(Sample* sample, uword pc, uword fp, uword sp)
1438 : sample_(sample),
1439 frame_iterator_(fp, sp, pc) {
1440 ASSERT(sample_ != NULL);
1441 }
1442
1443 ProfilerDartStackWalker(Sample* sample, uword fp)
1444 : sample_(sample),
1445 frame_iterator_(fp) {
1446 ASSERT(sample_ != NULL);
1447 }
1448
1449 int walk() {
1450 intptr_t frame_index = 0;
1451 StackFrame* frame = frame_iterator_.NextFrame();
1452 while (frame != NULL) {
1453 sample_->SetAt(frame_index, frame->pc());
1454 frame_index++;
1455 if (frame_index >= FLAG_profile_depth) {
1456 break;
1457 }
1458 frame = frame_iterator_.NextFrame();
1459 }
1460 return frame_index;
1461 }
1462
1463 private:
1464 Sample* sample_;
1465 DartFrameIterator frame_iterator_;
1466 };
1467
1409 // Notes on stack frame walking: 1468 // Notes on stack frame walking:
1410 // 1469 //
1411 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames 1470 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames
1412 // The stack frame walking code uses the frame pointer to traverse the stack. 1471 // The stack frame walking code uses the frame pointer to traverse the stack.
1413 // If the VM is compiled without frame pointers (which is the default on 1472 // If the VM is compiled without frame pointers (which is the default on
1414 // recent GCC versions with optimizing enabled) the stack walking code may 1473 // recent GCC versions with optimizing enabled) the stack walking code may
1415 // fail (sometimes leading to a crash). 1474 // fail (sometimes leading to a crash).
1416 // 1475 //
1417 class ProfilerSampleStackWalker : public ValueObject { 1476 class ProfilerNativeStackWalker : public ValueObject {
1418 public: 1477 public:
1419 ProfilerSampleStackWalker(Sample* sample, 1478 ProfilerNativeStackWalker(Sample* sample,
1420 uword stack_lower, 1479 uword stack_lower,
1421 uword stack_upper, 1480 uword stack_upper,
1422 uword pc, 1481 uword pc,
1423 uword fp, 1482 uword fp,
1424 uword sp) 1483 uword sp)
1425 : sample_(sample), 1484 : sample_(sample),
1426 stack_upper_(stack_upper), 1485 stack_upper_(stack_upper),
1427 original_pc_(pc), 1486 original_pc_(pc),
1428 original_fp_(fp), 1487 original_fp_(fp),
1429 original_sp_(sp), 1488 original_sp_(sp),
1430 lower_bound_(stack_lower) { 1489 lower_bound_(stack_lower) {
1431 ASSERT(sample_ != NULL); 1490 ASSERT(sample_ != NULL);
1432 } 1491 }
1433 1492
1434 int walk(Heap* heap, uword vm_tag) { 1493 int walk(Heap* heap) {
1435 const intptr_t kMaxStep = 0x1000; // 4K. 1494 const intptr_t kMaxStep = 0x1000; // 4K.
1436 const bool kWalkStack = true; // Walk the stack. 1495 const bool kWalkStack = true; // Walk the stack.
1437 // Always store the exclusive PC. 1496 // Always store the exclusive PC.
1438 sample_->SetAt(0, original_pc_); 1497 sample_->SetAt(0, original_pc_);
1439 // Always store the vm tag.
1440 sample_->set_vm_tag(vm_tag);
1441 if (!kWalkStack) { 1498 if (!kWalkStack) {
1442 // Not walking the stack, only took exclusive sample. 1499 // Not walking the stack, only took exclusive sample.
1443 return 1; 1500 return 1;
1444 } 1501 }
1445 uword* pc = reinterpret_cast<uword*>(original_pc_); 1502 uword* pc = reinterpret_cast<uword*>(original_pc_);
1446 uword* fp = reinterpret_cast<uword*>(original_fp_); 1503 uword* fp = reinterpret_cast<uword*>(original_fp_);
1447 uword* previous_fp = fp; 1504 uword* previous_fp = fp;
1448 if (original_sp_ > original_fp_) { 1505 if (original_sp_ > original_fp_) {
1449 // Stack pointer should not be above frame pointer. 1506 // Stack pointer should not be above frame pointer.
1450 return 1; 1507 return 1;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1527 const uword original_fp_; 1584 const uword original_fp_;
1528 const uword original_sp_; 1585 const uword original_sp_;
1529 uword lower_bound_; 1586 uword lower_bound_;
1530 }; 1587 };
1531 1588
1532 1589
1533 void Profiler::RecordSampleInterruptCallback( 1590 void Profiler::RecordSampleInterruptCallback(
1534 const InterruptedThreadState& state, 1591 const InterruptedThreadState& state,
1535 void* data) { 1592 void* data) {
1536 Isolate* isolate = reinterpret_cast<Isolate*>(data); 1593 Isolate* isolate = reinterpret_cast<Isolate*>(data);
1537 if (isolate == NULL) { 1594 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
1595 return;
1596 }
1597 if (isolate == Dart::vm_isolate()) {
1598 // Never sample the vm_isolate.
1599 return;
1600 }
siva 2014/04/08 16:27:54 Does it make sense to start the profiler before th
Cutch 2014/04/09 17:40:59 Isolate::SetCurrent expects the profiler to have b
siva 2014/04/09 23:28:11 I agree we don't want to make Isolate::SetCurrent
Cutch 2014/04/10 15:30:27 Done.
1601 if (!FLAG_profile_native_stack && (isolate->stub_code() == NULL)) {
1602 // ProfilerDartStackWalker requires stub code setup to be completed.
1538 return; 1603 return;
1539 } 1604 }
siva 2014/04/08 16:27:54 Instead of checking like this wouldn't it be more
Cutch 2014/04/09 17:40:59 See above.
1540 VMTagCounters* counters = isolate->vm_tag_counters(); 1605 VMTagCounters* counters = isolate->vm_tag_counters();
1541 ASSERT(counters != NULL); 1606 ASSERT(counters != NULL);
1542 counters->Increment(isolate->vm_tag()); 1607 counters->Increment(isolate->vm_tag());
1543 IsolateProfilerData* profiler_data = isolate->profiler_data(); 1608 IsolateProfilerData* profiler_data = isolate->profiler_data();
1544 if (profiler_data == NULL) { 1609 if (profiler_data == NULL) {
1545 return; 1610 return;
1546 } 1611 }
1547 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); 1612 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
1548 if (sample_buffer == NULL) { 1613 if (sample_buffer == NULL) {
1549 return; 1614 return;
1550 } 1615 }
1551 Sample* sample = sample_buffer->ReserveSample(); 1616 Sample* sample = sample_buffer->ReserveSample();
1552 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); 1617 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid);
1553 uword stack_lower = 0; 1618 sample->set_vm_tag(isolate->vm_tag());
1554 uword stack_upper = 0; 1619 if (FLAG_profile_native_stack) {
1555 isolate->GetStackBounds(&stack_lower, &stack_upper); 1620 // Collect native and Dart frames.
1556 if ((stack_lower == 0) || (stack_upper == 0)) { 1621 uword stack_lower = 0;
1557 stack_lower = 0; 1622 uword stack_upper = 0;
1558 stack_upper = 0; 1623 isolate->GetStackBounds(&stack_lower, &stack_upper);
1624 if ((stack_lower == 0) || (stack_upper == 0)) {
1625 stack_lower = 0;
1626 stack_upper = 0;
1627 }
1628 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper,
1629 state.pc, state.fp, state.sp);
1630 stackWalker.walk(isolate->heap());
1631 } else {
1632 if (isolate->top_exit_frame_info() != 0) {
1633 ProfilerDartStackWalker stackWalker(sample);
1634 stackWalker.walk();
1635 } else {
1636 // TODO(johnmccutchan): StackFrameIterator that is resilient to native
1637 // frames.
siva 2014/04/08 16:27:54 what does this TODO mean (for pure Dart frame walk
Cutch 2014/04/09 17:40:59 Slightly misworded but I want to support only coll
1638 }
1559 } 1639 }
1560 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
1561 state.pc, state.fp, state.sp);
1562 stackWalker.walk(isolate->heap(), isolate->vm_tag());
1563 } 1640 }
1564 1641
1565 } // namespace dart 1642 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698