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

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, 9 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 | « runtime/bin/vmservice/client/lib/src/observatory_elements/stack_trace.dart ('k') | 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, intptr_t serial) {
283 // Assert that exclusive ticks are never passed a valid serial number.
284 ASSERT((exclusive && (serial == -1)) || (!exclusive && (serial != -1)));
285 if (!exclusive && (inclusive_tick_serial_ == serial)) {
286 // We've already given this code object an inclusive tick for this sample.
287 return;
288 }
289 // Tick the code object.
290 if (exclusive) {
291 exclusive_ticks_++;
292 } else {
293 // Mark the last serial we ticked the inclusive count.
294 inclusive_tick_serial_ = serial;
295 inclusive_ticks_++;
296 }
297 // Tick the address entry.
275 const intptr_t length = address_table_->length(); 298 const intptr_t length = address_table_->length();
276 intptr_t i = 0; 299 intptr_t i = 0;
277 for (; i < length; i++) { 300 for (; i < length; i++) {
278 AddressEntry& entry = (*address_table_)[i]; 301 AddressEntry& entry = (*address_table_)[i];
279 if (entry.pc == pc) { 302 if (entry.pc == pc) {
280 entry.ticks++; 303 entry.tick(exclusive);
281 return; 304 return;
282 } 305 }
283 if (entry.pc > pc) { 306 if (entry.pc > pc) {
284 break; 307 break;
285 } 308 }
286 } 309 }
287 AddressEntry entry; 310 AddressEntry entry;
288 entry.pc = pc; 311 entry.pc = pc;
289 entry.ticks = 1; 312 entry.tick(exclusive);
290 if (i < length) { 313 if (i < length) {
291 // Insert at i. 314 // Insert at i.
292 address_table_->InsertAt(i, entry); 315 address_table_->InsertAt(i, entry);
293 } else { 316 } else {
294 // Add to end. 317 // Add to end.
295 address_table_->Add(entry); 318 address_table_->Add(entry);
296 } 319 }
297 } 320 }
298 321
322 void AddCaller(intptr_t index) {
323 AddCallEntry(callers_table_, index);
324 }
325
326 void AddCallee(intptr_t index) {
327 AddCallEntry(callees_table_, index);
328 }
299 329
300 void PrintToJSONArray(JSONArray* events, bool full) { 330 void PrintToJSONArray(JSONArray* events, bool full) {
301 JSONObject obj(events); 331 JSONObject obj(events);
302 obj.AddProperty("type", "ProfileCode"); 332 obj.AddProperty("type", "ProfileCode");
303 obj.AddProperty("kind", KindToCString(kind())); 333 obj.AddProperty("kind", KindToCString(kind()));
304 obj.AddPropertyF("inclusive_ticks", "%" Pd "", inclusive_ticks()); 334 obj.AddPropertyF("inclusive_ticks", "%" Pd "", inclusive_ticks());
305 obj.AddPropertyF("exclusive_ticks", "%" Pd "", exclusive_ticks()); 335 obj.AddPropertyF("exclusive_ticks", "%" Pd "", exclusive_ticks());
306 if (kind() == kDartCode) { 336 if (kind() == kDartCode) {
307 // Look up code in Dart heap. 337 // Look up code in Dart heap.
308 Code& code = Code::Handle(Code::LookupCode(start())); 338 Code& code = Code::Handle(Code::LookupCode(start()));
309 Function& func = Function::Handle(); 339 Function& func = Function::Handle();
310 ASSERT(!code.IsNull()); 340 ASSERT(!code.IsNull());
311 func ^= code.function(); 341 func ^= code.function();
312 if (func.IsNull()) { 342 if (func.IsNull()) {
313 if (name() == NULL) { 343 if (name() == NULL) {
314 GenerateAndSetSymbolName("Stub"); 344 const char* stub_name = StubCode::NameOfStub(start());
345 GenerateAndSetSymbolName(stub_name == NULL ? "Stub" : stub_name);
315 } 346 }
316 obj.AddPropertyF("start", "%" Px "", start()); 347 obj.AddPropertyF("start", "%" Px "", start());
317 obj.AddPropertyF("end", "%" Px "", end()); 348 obj.AddPropertyF("end", "%" Px "", end());
318 obj.AddProperty("name", name()); 349 obj.AddProperty("name", name());
319 } else { 350 } else {
320 obj.AddProperty("code", code, !full); 351 obj.AddProperty("code", code, !full);
321 } 352 }
322 } else if (kind() == kCollectedCode) { 353 } else if (kind() == kCollectedCode) {
323 if (name() == NULL) { 354 if (name() == NULL) {
324 GenerateAndSetSymbolName("Collected"); 355 GenerateAndSetSymbolName("Collected");
325 } 356 }
326 obj.AddPropertyF("start", "%" Px "", start()); 357 obj.AddPropertyF("start", "%" Px "", start());
327 obj.AddPropertyF("end", "%" Px "", end()); 358 obj.AddPropertyF("end", "%" Px "", end());
328 obj.AddProperty("name", name()); 359 obj.AddProperty("name", name());
329 } else { 360 } else {
330 ASSERT(kind() == kNativeCode); 361 ASSERT(kind() == kNativeCode);
331 if (name() == NULL) { 362 if (name() == NULL) {
332 GenerateAndSetSymbolName("Native"); 363 GenerateAndSetSymbolName("Native");
333 } 364 }
334 obj.AddPropertyF("start", "%" Px "", start()); 365 obj.AddPropertyF("start", "%" Px "", start());
335 obj.AddPropertyF("end", "%" Px "", end()); 366 obj.AddPropertyF("end", "%" Px "", end());
336 obj.AddProperty("name", name()); 367 obj.AddProperty("name", name());
337 } 368 }
338 { 369 {
339 JSONArray ticks(&obj, "ticks"); 370 JSONArray ticks(&obj, "ticks");
340 for (intptr_t i = 0; i < address_table_->length(); i++) { 371 for (intptr_t i = 0; i < address_table_->length(); i++) {
341 const AddressEntry& entry = (*address_table_)[i]; 372 const AddressEntry& entry = (*address_table_)[i];
342 ticks.AddValueF("%" Px "", entry.pc); 373 ticks.AddValueF("%" Px "", entry.pc);
343 ticks.AddValueF("%" Pd "", entry.ticks); 374 ticks.AddValueF("%" Pd "", entry.exclusive_ticks);
375 ticks.AddValueF("%" Pd "", entry.inclusive_ticks);
376 }
377 }
378 {
379 JSONArray callers(&obj, "callers");
380 for (intptr_t i = 0; i < callers_table_->length(); i++) {
381 const CallEntry& entry = (*callers_table_)[i];
382 callers.AddValueF("%" Pd "", entry.code_table_index);
383 callers.AddValueF("%" Pd "", entry.count);
384 }
385 }
386 {
387 JSONArray callees(&obj, "callees");
388 for (intptr_t i = 0; i < callees_table_->length(); i++) {
389 const CallEntry& entry = (*callees_table_)[i];
390 callees.AddValueF("%" Pd "", entry.code_table_index);
391 callees.AddValueF("%" Pd "", entry.count);
344 } 392 }
345 } 393 }
346 } 394 }
347 395
348 private: 396 private:
397 void AddCallEntry(ZoneGrowableArray<CallEntry>* table, intptr_t index) {
398 const intptr_t length = table->length();
399 intptr_t i = 0;
400 for (; i < length; i++) {
401 CallEntry& entry = (*table)[i];
402 if (entry.code_table_index == index) {
403 entry.count++;
404 return;
405 }
406 if (entry.code_table_index > index) {
407 break;
408 }
409 }
410 CallEntry entry;
411 entry.code_table_index = index;
412 entry.count = 1;
413 if (i < length) {
414 table->InsertAt(i, entry);
415 } else {
416 table->Add(entry);
417 }
418 }
419
349 void GenerateAndSetSymbolName(const char* prefix) { 420 void GenerateAndSetSymbolName(const char* prefix) {
350 const intptr_t kBuffSize = 512; 421 const intptr_t kBuffSize = 512;
351 char buff[kBuffSize]; 422 char buff[kBuffSize];
352 OS::SNPrint(&buff[0], kBuffSize-1, "%s [%" Px ", %" Px ")", 423 OS::SNPrint(&buff[0], kBuffSize-1, "%s [%" Px ", %" Px ")",
353 prefix, start(), end()); 424 prefix, start(), end());
354 SetName(buff); 425 SetName(buff);
355 } 426 }
356 427
357 Kind kind_; 428 Kind kind_;
358 uword start_; 429 uword start_;
359 uword end_; 430 uword end_;
360 intptr_t inclusive_ticks_; 431 intptr_t inclusive_ticks_;
361 intptr_t exclusive_ticks_; 432 intptr_t exclusive_ticks_;
433 intptr_t inclusive_tick_serial_;
362 const char* name_; 434 const char* name_;
363 ZoneGrowableArray<AddressEntry>* address_table_; 435 ZoneGrowableArray<AddressEntry>* address_table_;
364 436 ZoneGrowableArray<CallEntry>* callers_table_;
437 ZoneGrowableArray<CallEntry>* callees_table_;
365 DISALLOW_COPY_AND_ASSIGN(CodeRegion); 438 DISALLOW_COPY_AND_ASSIGN(CodeRegion);
366 }; 439 };
367 440
368 441
369 class ScopeStopwatch : public ValueObject { 442 class ScopeStopwatch : public ValueObject {
370 public: 443 public:
371 explicit ScopeStopwatch(const char* name) : name_(name) { 444 explicit ScopeStopwatch(const char* name) : name_(name) {
372 start_ = OS::GetCurrentTimeMillis(); 445 start_ = OS::GetCurrentTimeMillis();
373 } 446 }
374 447
(...skipping 21 matching lines...) Expand all
396 class ProfilerCodeRegionTable : public ValueObject { 469 class ProfilerCodeRegionTable : public ValueObject {
397 public: 470 public:
398 explicit ProfilerCodeRegionTable(Isolate* isolate) : 471 explicit ProfilerCodeRegionTable(Isolate* isolate) :
399 heap_(isolate->heap()), 472 heap_(isolate->heap()),
400 code_region_table_(new ZoneGrowableArray<CodeRegion*>(64)) { 473 code_region_table_(new ZoneGrowableArray<CodeRegion*>(64)) {
401 } 474 }
402 475
403 ~ProfilerCodeRegionTable() { 476 ~ProfilerCodeRegionTable() {
404 } 477 }
405 478
406 void AddTick(uword pc, bool exclusive, bool tick_address) { 479 void AddTick(uword pc, bool exclusive, intptr_t serial) {
407 intptr_t index = FindIndex(pc); 480 intptr_t index = FindIndex(pc);
408 if (index < 0) { 481 if (index < 0) {
409 CodeRegion* code_region = CreateCodeRegion(pc); 482 CodeRegion* code_region = CreateCodeRegion(pc);
410 ASSERT(code_region != NULL); 483 ASSERT(code_region != NULL);
411 index = InsertCodeRegion(code_region); 484 index = InsertCodeRegion(code_region);
412 } 485 }
413 ASSERT(index >= 0); 486 ASSERT(index >= 0);
414 ASSERT(index < code_region_table_->length()); 487 ASSERT(index < code_region_table_->length());
415 (*code_region_table_)[index]->AddTick(exclusive); 488
416 if (tick_address) { 489 // Update code object counters.
417 (*code_region_table_)[index]->AddTickAtAddress(pc); 490 (*code_region_table_)[index]->AddTickAtAddress(pc, exclusive, serial);
418 }
419 } 491 }
420 492
421 intptr_t Length() const { return code_region_table_->length(); } 493 intptr_t Length() const { return code_region_table_->length(); }
422 494
423 CodeRegion* At(intptr_t idx) { 495 CodeRegion* At(intptr_t idx) {
424 return (*code_region_table_)[idx]; 496 return (*code_region_table_)[idx];
425 } 497 }
426 498
499 intptr_t FindIndex(uword pc) const {
500 intptr_t index = FindRegionIndex(pc, &CompareLowerBound);
501 const CodeRegion* code_region = NULL;
502 if (index == code_region_table_->length()) {
503 // Not present.
504 return -1;
505 }
506 code_region = (*code_region_table_)[index];
507 if (code_region->contains(pc)) {
508 // Found at index.
509 return index;
510 }
511 return -1;
512 }
513
427 #if defined(DEBUG) 514 #if defined(DEBUG)
428 void Verify() { 515 void Verify() {
429 VerifyOrder(); 516 VerifyOrder();
430 VerifyOverlap(); 517 VerifyOverlap();
431 } 518 }
432 #endif 519 #endif
433 520
434 private: 521 private:
435 intptr_t FindRegionIndex(uword pc, RegionCompare comparator) { 522 intptr_t FindRegionIndex(uword pc, RegionCompare comparator) const {
436 ASSERT(comparator != NULL); 523 ASSERT(comparator != NULL);
437 intptr_t count = code_region_table_->length(); 524 intptr_t count = code_region_table_->length();
438 intptr_t first = 0; 525 intptr_t first = 0;
439 while (count > 0) { 526 while (count > 0) {
440 intptr_t it = first; 527 intptr_t it = first;
441 intptr_t step = count / 2; 528 intptr_t step = count / 2;
442 it += step; 529 it += step;
443 const CodeRegion* code_region = (*code_region_table_)[it]; 530 const CodeRegion* code_region = (*code_region_table_)[it];
444 if (comparator(pc, code_region->start(), code_region->end())) { 531 if (comparator(pc, code_region->start(), code_region->end())) {
445 first = ++it; 532 first = ++it;
446 count -= (step + 1); 533 count -= (step + 1);
447 } else { 534 } else {
448 count = step; 535 count = step;
449 } 536 }
450 } 537 }
451 return first; 538 return first;
452 } 539 }
453 540
454 static bool CompareUpperBound(uword pc, uword start, uword end) { 541 static bool CompareUpperBound(uword pc, uword start, uword end) {
455 return pc >= end; 542 return pc >= end;
456 } 543 }
457 544
458 static bool CompareLowerBound(uword pc, uword start, uword end) { 545 static bool CompareLowerBound(uword pc, uword start, uword end) {
459 return end <= pc; 546 return end <= pc;
460 } 547 }
461 548
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) { 549 CodeRegion* CreateCodeRegion(uword pc) {
478 Code& code = Code::Handle(Code::LookupCode(pc)); 550 Code& code = Code::Handle(Code::LookupCode(pc));
479 if (!code.IsNull()) { 551 if (!code.IsNull()) {
480 return new CodeRegion(CodeRegion::kDartCode, code.EntryPoint(), 552 return new CodeRegion(CodeRegion::kDartCode, code.EntryPoint(),
481 code.EntryPoint() + code.Size()); 553 code.EntryPoint() + code.Size());
482 } 554 }
483 if (heap_->CodeContains(pc)) { 555 if (heap_->CodeContains(pc)) {
484 const intptr_t kDartCodeAlignment = 0x10; 556 const intptr_t kDartCodeAlignment = 0x10;
485 const intptr_t kDartCodeAlignmentMask = ~(kDartCodeAlignment - 1); 557 const intptr_t kDartCodeAlignmentMask = ~(kDartCodeAlignment - 1);
486 return new CodeRegion(CodeRegion::kCollectedCode, pc, 558 return new CodeRegion(CodeRegion::kCollectedCode, pc,
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 672
601 class CodeRegionTableBuilder : public SampleVisitor { 673 class CodeRegionTableBuilder : public SampleVisitor {
602 public: 674 public:
603 CodeRegionTableBuilder(Isolate* isolate, 675 CodeRegionTableBuilder(Isolate* isolate,
604 ProfilerCodeRegionTable* code_region_table) 676 ProfilerCodeRegionTable* code_region_table)
605 : SampleVisitor(isolate), code_region_table_(code_region_table) { 677 : SampleVisitor(isolate), code_region_table_(code_region_table) {
606 frames_ = 0; 678 frames_ = 0;
607 } 679 }
608 680
609 void VisitSample(Sample* sample) { 681 void VisitSample(Sample* sample) {
610 code_region_table_->AddTick(sample->At(0), true, false); 682 // Give the bottom frame an exclusive tick.
611 // Give all frames an inclusive tick and tick the address. 683 code_region_table_->AddTick(sample->At(0), true, -1);
684 // Give all frames (including the bottom) an inclusive tick.
612 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 685 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
613 if (sample->At(i) == 0) { 686 if (sample->At(i) == 0) {
614 break; 687 break;
615 } 688 }
616 frames_++; 689 frames_++;
617 code_region_table_->AddTick(sample->At(i), false, true); 690 code_region_table_->AddTick(sample->At(i), false, visited());
618 } 691 }
619 } 692 }
620 693
621 intptr_t frames() const { return frames_; } 694 intptr_t frames() const { return frames_; }
695
622 private: 696 private:
623 intptr_t frames_; 697 intptr_t frames_;
624 ProfilerCodeRegionTable* code_region_table_; 698 ProfilerCodeRegionTable* code_region_table_;
625 }; 699 };
626 700
627 701
702 class CodeRegionTableCallersBuilder : public SampleVisitor {
703 public:
704 CodeRegionTableCallersBuilder(Isolate* isolate,
705 ProfilerCodeRegionTable* code_region_table)
706 : SampleVisitor(isolate), code_region_table_(code_region_table) {
707 ASSERT(code_region_table_ != NULL);
708 }
709
710 void VisitSample(Sample* sample) {
711 intptr_t current_index = code_region_table_->FindIndex(sample->At(0));
712 ASSERT(current_index != -1);
713 CodeRegion* current = code_region_table_->At(current_index);
714 intptr_t caller_index = -1;
715 CodeRegion* caller = NULL;
716 intptr_t callee_index = -1;
717 CodeRegion* callee = NULL;
718 for (intptr_t i = 1; i < FLAG_profile_depth; i++) {
719 if (sample->At(i) == 0) {
720 break;
721 }
722 caller_index = code_region_table_->FindIndex(sample->At(i));
723 ASSERT(caller_index != -1);
724 caller = code_region_table_->At(caller_index);
725 current->AddCaller(caller_index);
726 if (callee != NULL) {
727 current->AddCallee(callee_index);
728 }
729 // Move cursors.
730 callee_index = current_index;
731 callee = current;
732 current_index = caller_index;
733 current = caller;
734 }
735 }
736
737 private:
738 ProfilerCodeRegionTable* code_region_table_;
739 };
740
628 void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream, 741 void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream,
629 bool full) { 742 bool full) {
630 ASSERT(isolate == Isolate::Current()); 743 ASSERT(isolate == Isolate::Current());
631 // Disable profile interrupts while processing the buffer. 744 // Disable profile interrupts while processing the buffer.
632 EndExecution(isolate); 745 EndExecution(isolate);
633 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); 746 MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
634 IsolateProfilerData* profiler_data = isolate->profiler_data(); 747 IsolateProfilerData* profiler_data = isolate->profiler_data();
635 if (profiler_data == NULL) { 748 if (profiler_data == NULL) {
636 JSONObject error(stream); 749 JSONObject error(stream);
637 error.AddProperty("type", "Error"); 750 error.AddProperty("type", "Error");
638 error.AddProperty("text", "Isolate does not have profiling enabled."); 751 error.AddProperty("text", "Isolate does not have profiling enabled.");
639 return; 752 return;
640 } 753 }
641 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); 754 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
642 ASSERT(sample_buffer != NULL); 755 ASSERT(sample_buffer != NULL);
643 { 756 {
644 StackZone zone(isolate); 757 StackZone zone(isolate);
645 { 758 {
646 // Build code region table. 759 // Build code region table.
647 ProfilerCodeRegionTable code_region_table(isolate); 760 ProfilerCodeRegionTable code_region_table(isolate);
648 CodeRegionTableBuilder builder(isolate, &code_region_table); 761 CodeRegionTableBuilder builder(isolate, &code_region_table);
762 CodeRegionTableCallersBuilder build_callers(isolate, &code_region_table);
649 { 763 {
650 ScopeStopwatch sw("CodeTableBuild"); 764 ScopeStopwatch sw("CodeTableBuild");
651 sample_buffer->VisitSamples(&builder); 765 sample_buffer->VisitSamples(&builder);
652 } 766 }
653 #if defined(DEBUG) 767 #if defined(DEBUG)
654 code_region_table.Verify(); 768 code_region_table.Verify();
655 #endif 769 #endif
770 {
771 ScopeStopwatch sw("CodeTableCallersBuild");
772 sample_buffer->VisitSamples(&build_callers);
773 }
656 // Number of samples we processed. 774 // Number of samples we processed.
657 intptr_t samples = builder.visited(); 775 intptr_t samples = builder.visited();
658 intptr_t frames = builder.frames(); 776 intptr_t frames = builder.frames();
659 if (FLAG_trace_profiled_isolates) { 777 if (FLAG_trace_profiled_isolates) {
660 OS::Print("%" Pd " frames produced %" Pd " code objects.\n", 778 OS::Print("%" Pd " frames produced %" Pd " code objects.\n",
661 frames, code_region_table.Length()); 779 frames, code_region_table.Length());
662 } 780 }
663 { 781 {
664 ScopeStopwatch sw("CodeTableStream"); 782 ScopeStopwatch sw("CodeTableStream");
665 // Serialize to JSON. 783 // Serialize to JSON.
666 JSONObject obj(stream); 784 JSONObject obj(stream);
667 obj.AddProperty("type", "Profile"); 785 obj.AddProperty("type", "Profile");
668 obj.AddProperty("samples", samples); 786 obj.AddProperty("samples", samples);
669 JSONArray codes(&obj, "codes"); 787 JSONArray codes(&obj, "codes");
670 for (intptr_t i = 0; i < code_region_table.Length(); i++) { 788 for (intptr_t i = 0; i < code_region_table.Length(); i++) {
671 CodeRegion* region = code_region_table.At(i); 789 CodeRegion* region = code_region_table.At(i);
672 ASSERT(region != NULL); 790 ASSERT(region != NULL);
673 region->PrintToJSONArray(&codes, false); 791 region->PrintToJSONArray(&codes, full);
674 } 792 }
675 } 793 }
676 } 794 }
677 } 795 }
678 // Enable profile interrupts. 796 // Enable profile interrupts.
679 BeginExecution(isolate); 797 BeginExecution(isolate);
680 } 798 }
681 799
682 800
683 void Profiler::WriteProfile(Isolate* isolate) { 801 void Profiler::WriteProfile(Isolate* isolate) {
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 stack_lower = 0; 991 stack_lower = 0;
874 stack_upper = 0; 992 stack_upper = 0;
875 } 993 }
876 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, 994 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
877 state.pc, state.fp, state.sp); 995 state.pc, state.fp, state.sp);
878 stackWalker.walk(); 996 stackWalker.walk();
879 } 997 }
880 998
881 999
882 } // namespace dart 1000 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/bin/vmservice/client/lib/src/observatory_elements/stack_trace.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698