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

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

Issue 168833005: Add callers and callees to profiler output (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 if (!FLAG_profile) { 155 if (!FLAG_profile) {
156 return; 156 return;
157 } 157 }
158 ASSERT(initialized_); 158 ASSERT(initialized_);
159 ThreadInterrupter::Unregister(); 159 ThreadInterrupter::Unregister();
160 } 160 }
161 161
162 162
163 struct AddressEntry { 163 struct AddressEntry {
164 uword pc; 164 uword pc;
165 intptr_t ticks; 165 intptr_t exclusive_ticks;
166 intptr_t inclusive_ticks;
167
168 void tick(bool exclusive) {
169 if (exclusive) {
170 exclusive_ticks++;
171 } else {
172 inclusive_ticks++;
173 }
174 }
175 };
176
177 struct CallEntry {
178 intptr_t code_table_index;
179 intptr_t count;
166 }; 180 };
167 181
168 typedef bool (*RegionCompare)(uword pc, uword region_start, uword region_end); 182 typedef bool (*RegionCompare)(uword pc, uword region_start, uword region_end);
169 183
170 // A region of code. Each region is a kind of code (Dart, Collected, or Native). 184 // A region of code. Each region is a kind of code (Dart, Collected, or Native).
171 class CodeRegion : public ZoneAllocated { 185 class CodeRegion : public ZoneAllocated {
172 public: 186 public:
173 enum Kind { 187 enum Kind {
174 kDartCode, 188 kDartCode,
175 kCollectedCode, 189 kCollectedCode,
176 kNativeCode 190 kNativeCode
177 }; 191 };
178 192
179 CodeRegion(Kind kind, uword start, uword end) : 193 CodeRegion(Kind kind, uword start, uword end) :
180 kind_(kind), 194 kind_(kind),
181 start_(start), 195 start_(start),
182 end_(end), 196 end_(end),
183 inclusive_ticks_(0), 197 inclusive_ticks_(0),
184 exclusive_ticks_(0), 198 exclusive_ticks_(0),
185 name_(NULL), 199 name_(NULL),
186 address_table_(new ZoneGrowableArray<AddressEntry>()) { 200 address_table_(new ZoneGrowableArray<AddressEntry>()),
201 callers_table_(new ZoneGrowableArray<CallEntry>()),
202 callees_table_(new ZoneGrowableArray<CallEntry>()) {
187 ASSERT(start_ < end_); 203 ASSERT(start_ < end_);
188 } 204 }
189 205
190 ~CodeRegion() { 206 ~CodeRegion() {
191 } 207 }
192 208
193 uword start() const { return start_; } 209 uword start() const { return start_; }
194 void set_start(uword start) { 210 void set_start(uword start) {
195 start_ = start; 211 start_ = start;
196 } 212 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 return "Dart"; 267 return "Dart";
252 case kCollectedCode: 268 case kCollectedCode:
253 return "Collected"; 269 return "Collected";
254 case kNativeCode: 270 case kNativeCode:
255 return "Native"; 271 return "Native";
256 } 272 }
257 UNREACHABLE(); 273 UNREACHABLE();
258 return NULL; 274 return NULL;
259 } 275 }
260 276
261 void AddTick(bool exclusive) {
262 if (exclusive) {
263 exclusive_ticks_++;
264 } else {
265 inclusive_ticks_++;
266 }
267 }
268
269 void DebugPrint() const { 277 void DebugPrint() const {
270 printf("%s [%" Px ", %" Px ") %s\n", KindToCString(kind_), start(), end(), 278 printf("%s [%" Px ", %" Px ") %s\n", KindToCString(kind_), start(), end(),
271 name_); 279 name_);
272 } 280 }
273 281
274 void AddTickAtAddress(uword pc) { 282 void AddTickAtAddress(uword pc, bool exclusive) {
283 // Tick the code object.
284 if (exclusive) {
285 exclusive_ticks_++;
286 } else {
287 inclusive_ticks_++;
288 }
289 // Tick the address entry.
275 const intptr_t length = address_table_->length(); 290 const intptr_t length = address_table_->length();
276 intptr_t i = 0; 291 intptr_t i = 0;
277 for (; i < length; i++) { 292 for (; i < length; i++) {
278 AddressEntry& entry = (*address_table_)[i]; 293 AddressEntry& entry = (*address_table_)[i];
279 if (entry.pc == pc) { 294 if (entry.pc == pc) {
280 entry.ticks++; 295 entry.tick(exclusive);
281 return; 296 return;
282 } 297 }
283 if (entry.pc > pc) { 298 if (entry.pc > pc) {
284 break; 299 break;
285 } 300 }
286 } 301 }
287 AddressEntry entry; 302 AddressEntry entry;
288 entry.pc = pc; 303 entry.pc = pc;
289 entry.ticks = 1; 304 entry.tick(exclusive);
290 if (i < length) { 305 if (i < length) {
291 // Insert at i. 306 // Insert at i.
292 address_table_->InsertAt(i, entry); 307 address_table_->InsertAt(i, entry);
293 } else { 308 } else {
294 // Add to end. 309 // Add to end.
295 address_table_->Add(entry); 310 address_table_->Add(entry);
296 } 311 }
297 } 312 }
298 313
314 void AddCaller(intptr_t index) {
315 const intptr_t length = callers_table_->length();
316 intptr_t i = 0;
317 for (; i < length; i++) {
318 CallEntry& entry = (*callers_table_)[i];
319 if (entry.code_table_index == index) {
320 entry.count++;
321 return;
322 }
323 if (entry.code_table_index > index) {
324 break;
325 }
326 }
327 CallEntry entry;
328 entry.code_table_index = index;
329 entry.count = 1;
330 if (i < length) {
331 callers_table_->InsertAt(i, entry);
332 } else {
333 callers_table_->Add(entry);
334 }
335 }
336
337 void AddCallee(intptr_t index) {
338 const intptr_t length = callees_table_->length();
339 intptr_t i = 0;
340 for (; i < length; i++) {
341 CallEntry& entry = (*callees_table_)[i];
342 if (entry.code_table_index == index) {
343 entry.count++;
344 return;
345 }
346 if (entry.code_table_index > index) {
347 break;
348 }
349 }
350 CallEntry entry;
351 entry.code_table_index = index;
352 entry.count = 1;
353 if (i < length) {
354 callees_table_->InsertAt(i, entry);
355 } else {
356 callees_table_->Add(entry);
357 }
358 }
siva 2014/02/21 22:23:48 These two functions are identical except for the t
Cutch 2014/02/24 15:18:56 Done.
299 359
300 void PrintToJSONArray(JSONArray* events, bool full) { 360 void PrintToJSONArray(JSONArray* events, bool full) {
301 JSONObject obj(events); 361 JSONObject obj(events);
302 obj.AddProperty("type", "ProfileCode"); 362 obj.AddProperty("type", "ProfileCode");
303 obj.AddProperty("kind", KindToCString(kind())); 363 obj.AddProperty("kind", KindToCString(kind()));
304 obj.AddPropertyF("inclusive_ticks", "%" Pd "", inclusive_ticks()); 364 obj.AddPropertyF("inclusive_ticks", "%" Pd "", inclusive_ticks());
305 obj.AddPropertyF("exclusive_ticks", "%" Pd "", exclusive_ticks()); 365 obj.AddPropertyF("exclusive_ticks", "%" Pd "", exclusive_ticks());
306 if (kind() == kDartCode) { 366 if (kind() == kDartCode) {
307 // Look up code in Dart heap. 367 // Look up code in Dart heap.
308 Code& code = Code::Handle(Code::LookupCode(start())); 368 Code& code = Code::Handle(Code::LookupCode(start()));
(...skipping 24 matching lines...) Expand all
333 } 393 }
334 obj.AddPropertyF("start", "%" Px "", start()); 394 obj.AddPropertyF("start", "%" Px "", start());
335 obj.AddPropertyF("end", "%" Px "", end()); 395 obj.AddPropertyF("end", "%" Px "", end());
336 obj.AddProperty("name", name()); 396 obj.AddProperty("name", name());
337 } 397 }
338 { 398 {
339 JSONArray ticks(&obj, "ticks"); 399 JSONArray ticks(&obj, "ticks");
340 for (intptr_t i = 0; i < address_table_->length(); i++) { 400 for (intptr_t i = 0; i < address_table_->length(); i++) {
341 const AddressEntry& entry = (*address_table_)[i]; 401 const AddressEntry& entry = (*address_table_)[i];
342 ticks.AddValueF("%" Px "", entry.pc); 402 ticks.AddValueF("%" Px "", entry.pc);
343 ticks.AddValueF("%" Pd "", entry.ticks); 403 ticks.AddValueF("%" Pd "", entry.exclusive_ticks);
404 ticks.AddValueF("%" Pd "", entry.inclusive_ticks);
405 }
406 }
407 {
408 JSONArray callers(&obj, "callers");
409 for (intptr_t i = 0; i < callers_table_->length(); i++) {
410 const CallEntry& entry = (*callers_table_)[i];
411 callers.AddValueF("%" Pd "", entry.code_table_index);
412 callers.AddValueF("%" Pd "", entry.count);
413 }
414 }
415 {
416 JSONArray callers(&obj, "callees");
siva 2014/02/21 22:23:48 name the variable callees instead of callers to ma
Cutch 2014/02/24 15:18:56 Done.
417 for (intptr_t i = 0; i < callees_table_->length(); i++) {
418 const CallEntry& entry = (*callees_table_)[i];
419 callers.AddValueF("%" Pd "", entry.code_table_index);
420 callers.AddValueF("%" Pd "", entry.count);
344 } 421 }
345 } 422 }
346 } 423 }
347 424
348 private: 425 private:
349 void GenerateAndSetSymbolName(const char* prefix) { 426 void GenerateAndSetSymbolName(const char* prefix) {
350 const intptr_t kBuffSize = 512; 427 const intptr_t kBuffSize = 512;
351 char buff[kBuffSize]; 428 char buff[kBuffSize];
352 OS::SNPrint(&buff[0], kBuffSize-1, "%s [%" Px ", %" Px ")", 429 OS::SNPrint(&buff[0], kBuffSize-1, "%s [%" Px ", %" Px ")",
353 prefix, start(), end()); 430 prefix, start(), end());
354 SetName(buff); 431 SetName(buff);
355 } 432 }
356 433
357 Kind kind_; 434 Kind kind_;
358 uword start_; 435 uword start_;
359 uword end_; 436 uword end_;
360 intptr_t inclusive_ticks_; 437 intptr_t inclusive_ticks_;
361 intptr_t exclusive_ticks_; 438 intptr_t exclusive_ticks_;
362 const char* name_; 439 const char* name_;
363 ZoneGrowableArray<AddressEntry>* address_table_; 440 ZoneGrowableArray<AddressEntry>* address_table_;
364 441 ZoneGrowableArray<CallEntry>* callers_table_;
442 ZoneGrowableArray<CallEntry>* callees_table_;
365 DISALLOW_COPY_AND_ASSIGN(CodeRegion); 443 DISALLOW_COPY_AND_ASSIGN(CodeRegion);
366 }; 444 };
367 445
368 446
369 class ScopeStopwatch : public ValueObject { 447 class ScopeStopwatch : public ValueObject {
370 public: 448 public:
371 explicit ScopeStopwatch(const char* name) : name_(name) { 449 explicit ScopeStopwatch(const char* name) : name_(name) {
372 start_ = OS::GetCurrentTimeMillis(); 450 start_ = OS::GetCurrentTimeMillis();
373 } 451 }
374 452
(...skipping 14 matching lines...) Expand all
389 const char* name_; 467 const char* name_;
390 intptr_t start_; 468 intptr_t start_;
391 }; 469 };
392 470
393 471
394 // All code regions. Code region tables are built on demand when a profile 472 // All code regions. Code region tables are built on demand when a profile
395 // is requested (through the service or on isolate shutdown). 473 // is requested (through the service or on isolate shutdown).
396 class ProfilerCodeRegionTable : public ValueObject { 474 class ProfilerCodeRegionTable : public ValueObject {
397 public: 475 public:
398 explicit ProfilerCodeRegionTable(Isolate* isolate) : 476 explicit ProfilerCodeRegionTable(Isolate* isolate) :
477 inclusive_ticks_(0),
478 exclusive_ticks_(0),
399 heap_(isolate->heap()), 479 heap_(isolate->heap()),
400 code_region_table_(new ZoneGrowableArray<CodeRegion*>(64)) { 480 code_region_table_(new ZoneGrowableArray<CodeRegion*>(64)) {
401 } 481 }
402 482
403 ~ProfilerCodeRegionTable() { 483 ~ProfilerCodeRegionTable() {
404 } 484 }
405 485
406 void AddTick(uword pc, bool exclusive, bool tick_address) { 486 void AddTick(uword pc, bool exclusive) {
407 intptr_t index = FindIndex(pc); 487 intptr_t index = FindIndex(pc);
408 if (index < 0) { 488 if (index < 0) {
409 CodeRegion* code_region = CreateCodeRegion(pc); 489 CodeRegion* code_region = CreateCodeRegion(pc);
410 ASSERT(code_region != NULL); 490 ASSERT(code_region != NULL);
411 index = InsertCodeRegion(code_region); 491 index = InsertCodeRegion(code_region);
412 } 492 }
413 ASSERT(index >= 0); 493 ASSERT(index >= 0);
414 ASSERT(index < code_region_table_->length()); 494 ASSERT(index < code_region_table_->length());
415 (*code_region_table_)[index]->AddTick(exclusive); 495
416 if (tick_address) { 496 // Update global counters.
417 (*code_region_table_)[index]->AddTickAtAddress(pc); 497 if (exclusive) {
498 exclusive_ticks_++;
499 } else {
500 inclusive_ticks_++;
418 } 501 }
502
503 // Update code object counters.
504 (*code_region_table_)[index]->AddTickAtAddress(pc, exclusive);
419 } 505 }
420 506
421 intptr_t Length() const { return code_region_table_->length(); } 507 intptr_t Length() const { return code_region_table_->length(); }
422 508
423 CodeRegion* At(intptr_t idx) { 509 CodeRegion* At(intptr_t idx) {
424 return (*code_region_table_)[idx]; 510 return (*code_region_table_)[idx];
425 } 511 }
426 512
513 intptr_t exclusive_ticks() const { return exclusive_ticks_; }
514
515 intptr_t inclusive_ticks() const { return inclusive_ticks_; }
516
517 intptr_t FindIndex(uword pc) {
siva 2014/02/21 22:23:48 const function too?
Cutch 2014/02/24 15:18:56 Done.
518 intptr_t index = FindRegionIndex(pc, &CompareLowerBound);
519 const CodeRegion* code_region = NULL;
520 if (index == code_region_table_->length()) {
521 // Not present.
522 return -1;
523 }
524 code_region = (*code_region_table_)[index];
525 if (code_region->contains(pc)) {
526 // Found at index.
527 return index;
528 }
529 return -1;
530 }
531
427 #if defined(DEBUG) 532 #if defined(DEBUG)
428 void Verify() { 533 void Verify() {
429 VerifyOrder(); 534 VerifyOrder();
430 VerifyOverlap(); 535 VerifyOverlap();
431 } 536 }
432 #endif 537 #endif
433 538
434 private: 539 private:
435 intptr_t FindRegionIndex(uword pc, RegionCompare comparator) { 540 intptr_t FindRegionIndex(uword pc, RegionCompare comparator) {
436 ASSERT(comparator != NULL); 541 ASSERT(comparator != NULL);
(...skipping 15 matching lines...) Expand all
452 } 557 }
453 558
454 static bool CompareUpperBound(uword pc, uword start, uword end) { 559 static bool CompareUpperBound(uword pc, uword start, uword end) {
455 return pc >= end; 560 return pc >= end;
456 } 561 }
457 562
458 static bool CompareLowerBound(uword pc, uword start, uword end) { 563 static bool CompareLowerBound(uword pc, uword start, uword end) {
459 return end <= pc; 564 return end <= pc;
460 } 565 }
461 566
462 intptr_t FindIndex(uword pc) {
463 intptr_t index = FindRegionIndex(pc, &CompareLowerBound);
464 const CodeRegion* code_region = NULL;
465 if (index == code_region_table_->length()) {
466 // Not present.
467 return -1;
468 }
469 code_region = (*code_region_table_)[index];
470 if (code_region->contains(pc)) {
471 // Found at index.
472 return index;
473 }
474 return -1;
475 }
476
477 CodeRegion* CreateCodeRegion(uword pc) { 567 CodeRegion* CreateCodeRegion(uword pc) {
478 Code& code = Code::Handle(Code::LookupCode(pc)); 568 Code& code = Code::Handle(Code::LookupCode(pc));
479 if (!code.IsNull()) { 569 if (!code.IsNull()) {
480 return new CodeRegion(CodeRegion::kDartCode, code.EntryPoint(), 570 return new CodeRegion(CodeRegion::kDartCode, code.EntryPoint(),
481 code.EntryPoint() + code.Size()); 571 code.EntryPoint() + code.Size());
482 } 572 }
483 if (heap_->CodeContains(pc)) { 573 if (heap_->CodeContains(pc)) {
484 const intptr_t kDartCodeAlignment = 0x10; 574 const intptr_t kDartCodeAlignment = 0x10;
485 const intptr_t kDartCodeAlignmentMask = ~(kDartCodeAlignment - 1); 575 const intptr_t kDartCodeAlignmentMask = ~(kDartCodeAlignment - 1);
486 return new CodeRegion(CodeRegion::kCollectedCode, pc, 576 return new CodeRegion(CodeRegion::kCollectedCode, pc,
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 CodeRegion* b = (*code_region_table_)[j]; 676 CodeRegion* b = (*code_region_table_)[j];
587 ASSERT(!a->contains(b->start()) && 677 ASSERT(!a->contains(b->start()) &&
588 !a->contains(b->end() - 1) && 678 !a->contains(b->end() - 1) &&
589 !b->contains(a->start()) && 679 !b->contains(a->start()) &&
590 !b->contains(a->end() - 1)); 680 !b->contains(a->end() - 1));
591 } 681 }
592 } 682 }
593 } 683 }
594 #endif 684 #endif
595 685
686 intptr_t inclusive_ticks_;
687 intptr_t exclusive_ticks_;
596 Heap* heap_; 688 Heap* heap_;
597 ZoneGrowableArray<CodeRegion*>* code_region_table_; 689 ZoneGrowableArray<CodeRegion*>* code_region_table_;
598 }; 690 };
599 691
600 692
601 class CodeRegionTableBuilder : public SampleVisitor { 693 class CodeRegionTableBuilder : public SampleVisitor {
602 public: 694 public:
603 CodeRegionTableBuilder(Isolate* isolate, 695 CodeRegionTableBuilder(Isolate* isolate,
604 ProfilerCodeRegionTable* code_region_table) 696 ProfilerCodeRegionTable* code_region_table)
605 : SampleVisitor(isolate), code_region_table_(code_region_table) { 697 : SampleVisitor(isolate), code_region_table_(code_region_table) {
606 frames_ = 0; 698 frames_ = 0;
607 } 699 }
608 700
609 void VisitSample(Sample* sample) { 701 void VisitSample(Sample* sample) {
610 code_region_table_->AddTick(sample->At(0), true, false); 702 // Give the bottom frame an exclusive tick.
611 // Give all frames an inclusive tick and tick the address. 703 code_region_table_->AddTick(sample->At(0), true);
704 // Give all frames (including the bottom) an inclusive tick.
612 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 705 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
613 if (sample->At(i) == 0) { 706 if (sample->At(i) == 0) {
614 break; 707 break;
615 } 708 }
616 frames_++; 709 frames_++;
617 code_region_table_->AddTick(sample->At(i), false, true); 710 code_region_table_->AddTick(sample->At(i), false);
618 } 711 }
619 } 712 }
620 713
621 intptr_t frames() const { return frames_; } 714 intptr_t frames() const { return frames_; }
715
622 private: 716 private:
623 intptr_t frames_; 717 intptr_t frames_;
624 ProfilerCodeRegionTable* code_region_table_; 718 ProfilerCodeRegionTable* code_region_table_;
625 }; 719 };
626 720
627 721
722 class CodeRegionTableCallersBuilder : public SampleVisitor {
723 public:
724 CodeRegionTableCallersBuilder(Isolate* isolate,
725 ProfilerCodeRegionTable* code_region_table)
726 : SampleVisitor(isolate), code_region_table_(code_region_table) {
727 ASSERT(code_region_table_ != NULL);
728 }
729
730 void VisitSample(Sample* sample) {
731 intptr_t current_index = code_region_table_->FindIndex(sample->At(0));
732 ASSERT(current_index != -1);
733 CodeRegion* current = code_region_table_->At(current_index);
734 intptr_t caller_index = -1;
735 CodeRegion* caller = NULL;
736 intptr_t callee_index = -1;
737 CodeRegion* callee = NULL;
738 for (intptr_t i = 1; i < FLAG_profile_depth; i++) {
739 if (sample->At(i) == 0) {
740 break;
741 }
742 caller_index = code_region_table_->FindIndex(sample->At(i));
743 ASSERT(caller_index != -1);
744 caller = code_region_table_->At(caller_index);
745 current->AddCaller(caller_index);
746 if (callee != NULL) {
747 current->AddCallee(callee_index);
748 }
749 // Move cursors.
750 callee_index = current_index;
751 callee = current;
752 current_index = caller_index;
753 current = caller;
754 }
755 }
756
757 private:
758 ProfilerCodeRegionTable* code_region_table_;
759 };
760
628 void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream, 761 void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream,
629 bool full) { 762 bool full) {
630 ASSERT(isolate == Isolate::Current()); 763 ASSERT(isolate == Isolate::Current());
631 // Disable profile interrupts while processing the buffer. 764 // Disable profile interrupts while processing the buffer.
632 EndExecution(isolate); 765 EndExecution(isolate);
633 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); 766 MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
634 IsolateProfilerData* profiler_data = isolate->profiler_data(); 767 IsolateProfilerData* profiler_data = isolate->profiler_data();
635 if (profiler_data == NULL) { 768 if (profiler_data == NULL) {
636 JSONObject error(stream); 769 JSONObject error(stream);
637 error.AddProperty("type", "Error"); 770 error.AddProperty("type", "Error");
638 error.AddProperty("text", "Isolate does not have profiling enabled."); 771 error.AddProperty("text", "Isolate does not have profiling enabled.");
639 return; 772 return;
640 } 773 }
641 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); 774 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
642 ASSERT(sample_buffer != NULL); 775 ASSERT(sample_buffer != NULL);
643 { 776 {
644 StackZone zone(isolate); 777 StackZone zone(isolate);
645 { 778 {
646 // Build code region table. 779 // Build code region table.
647 ProfilerCodeRegionTable code_region_table(isolate); 780 ProfilerCodeRegionTable code_region_table(isolate);
648 CodeRegionTableBuilder builder(isolate, &code_region_table); 781 CodeRegionTableBuilder builder(isolate, &code_region_table);
782 CodeRegionTableCallersBuilder build_callers(isolate, &code_region_table);
649 { 783 {
650 ScopeStopwatch sw("CodeTableBuild"); 784 ScopeStopwatch sw("CodeTableBuild");
651 sample_buffer->VisitSamples(&builder); 785 sample_buffer->VisitSamples(&builder);
652 } 786 }
653 #if defined(DEBUG) 787 #if defined(DEBUG)
654 code_region_table.Verify(); 788 code_region_table.Verify();
655 #endif 789 #endif
790 {
791 ScopeStopwatch sw("CodeTableCallersBuild");
792 sample_buffer->VisitSamples(&build_callers);
793 }
656 // Number of samples we processed. 794 // Number of samples we processed.
657 intptr_t samples = builder.visited();
658 intptr_t frames = builder.frames(); 795 intptr_t frames = builder.frames();
659 if (FLAG_trace_profiled_isolates) { 796 if (FLAG_trace_profiled_isolates) {
660 OS::Print("%" Pd " frames produced %" Pd " code objects.\n", 797 OS::Print("%" Pd " frames produced %" Pd " code objects.\n",
661 frames, code_region_table.Length()); 798 frames, code_region_table.Length());
662 } 799 }
663 { 800 {
664 ScopeStopwatch sw("CodeTableStream"); 801 ScopeStopwatch sw("CodeTableStream");
665 // Serialize to JSON. 802 // Serialize to JSON.
666 JSONObject obj(stream); 803 JSONObject obj(stream);
667 obj.AddProperty("type", "Profile"); 804 obj.AddProperty("type", "Profile");
668 obj.AddProperty("samples", samples); 805 obj.AddProperty("exclusive_ticks", code_region_table.exclusive_ticks());
806 obj.AddProperty("inclusive_ticks", code_region_table.inclusive_ticks());
669 JSONArray codes(&obj, "codes"); 807 JSONArray codes(&obj, "codes");
670 for (intptr_t i = 0; i < code_region_table.Length(); i++) { 808 for (intptr_t i = 0; i < code_region_table.Length(); i++) {
671 CodeRegion* region = code_region_table.At(i); 809 CodeRegion* region = code_region_table.At(i);
672 ASSERT(region != NULL); 810 ASSERT(region != NULL);
673 region->PrintToJSONArray(&codes, false); 811 region->PrintToJSONArray(&codes, false);
674 } 812 }
675 } 813 }
676 } 814 }
677 } 815 }
678 // Enable profile interrupts. 816 // Enable profile interrupts.
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 stack_lower = 0; 1011 stack_lower = 0;
874 stack_upper = 0; 1012 stack_upper = 0;
875 } 1013 }
876 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, 1014 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
877 state.pc, state.fp, state.sp); 1015 state.pc, state.fp, state.sp);
878 stackWalker.walk(); 1016 stackWalker.walk();
879 } 1017 }
880 1018
881 1019
882 } // namespace dart 1020 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698