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

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

Issue 201213004: Use VM tag in profile and add stack trace trie (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
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 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 194
195 void tick(bool exclusive) { 195 void tick(bool exclusive) {
196 if (exclusive) { 196 if (exclusive) {
197 exclusive_ticks++; 197 exclusive_ticks++;
198 } else { 198 } else {
199 inclusive_ticks++; 199 inclusive_ticks++;
200 } 200 }
201 } 201 }
202 }; 202 };
203 203
204
204 struct CallEntry { 205 struct CallEntry {
205 intptr_t code_table_index; 206 intptr_t code_table_index;
206 intptr_t count; 207 intptr_t count;
207 }; 208 };
208 209
210
209 typedef bool (*RegionCompare)(uword pc, uword region_start, uword region_end); 211 typedef bool (*RegionCompare)(uword pc, uword region_start, uword region_end);
210 212
siva 2014/03/18 00:05:20 blank line needed to maintain 2 blank lines.
Cutch 2014/03/18 14:39:19 Done.
213 class CodeRegionTrieNode : public ZoneAllocated {
214 public:
215 explicit CodeRegionTrieNode(intptr_t code_region_index)
216 : code_region_index_(code_region_index),
217 count_(0),
218 children_(new ZoneGrowableArray<CodeRegionTrieNode*>()) {
219 }
220
221 void Tick() {
222 ASSERT(code_region_index_ >= 0);
223 count_++;
224 }
225
226 intptr_t count() const {
227 ASSERT(code_region_index_ >= 0);
228 return count_;
229 }
230
231 intptr_t code_region_index() const {
232 return code_region_index_;
233 }
234
235 CodeRegionTrieNode* GetChild(intptr_t child_code_region_index) {
236 const intptr_t length = children_->length();
237 intptr_t i = 0;
238 for (; i < length; i++) {
siva 2014/03/18 00:05:20 might be more readable as: while (i < length) { .
Cutch 2014/03/18 14:39:19 Done.
239 CodeRegionTrieNode* child = (*children_)[i];
240 if (child->code_region_index() == child_code_region_index) {
241 return child;
242 }
243 if (child->code_region_index() > child_code_region_index) {
244 break;
245 }
246 }
247 // New code region.
248 CodeRegionTrieNode* child = new CodeRegionTrieNode(child_code_region_index);
249 if (i < length) {
250 // Insert at i.
251 children_->InsertAt(i, child);
252 } else {
253 // Add to end.
254 children_->Add(child);
255 }
256 return child;
257 }
258
259 void RecursiveSort() {
260 children_->Sort(CodeRegionTrieNodeCompare);
261 ZoneGrowableArray<CodeRegionTrieNode*>& kids = children();
262 intptr_t child_count = kids.length();
263 // Recurse.
264 for (intptr_t i = 0; i < child_count; i++) {
265 kids[i]->RecursiveSort();
266 }
267 }
268
269 void PrintToJSONArray(JSONArray* array) {
siva 2014/03/18 00:05:20 void PrintToJSONArray(....) const {
Cutch 2014/03/18 14:39:19 Done.
270 ASSERT(array != NULL);
271 // Write CodeRegion index.
272 array->AddValue(code_region_index_);
273 // Write count.
274 array->AddValue(count_);
275 // Write number of children.
276 ZoneGrowableArray<CodeRegionTrieNode*>& kids = children();
277 intptr_t child_count = kids.length();
278 array->AddValue(child_count);
279 // Recurse.
280 for (intptr_t i = 0; i < child_count; i++) {
281 kids[i]->PrintToJSONArray(array);
282 }
283 }
284
285 ZoneGrowableArray<CodeRegionTrieNode*>& children() const {
286 return *children_;
287 }
siva 2014/03/18 00:05:20 Why not club this accessor with the other accessor
Cutch 2014/03/18 14:39:19 Done.
288
289 private:
290 static int CodeRegionTrieNodeCompare(CodeRegionTrieNode* const* a,
291 CodeRegionTrieNode* const* b) {
292 ASSERT(a != NULL);
293 ASSERT(b != NULL);
294 return (*b)->count() - (*a)->count();
295 }
296
297 const intptr_t code_region_index_;
298 intptr_t count_;
299 ZoneGrowableArray<CodeRegionTrieNode*>* children_;
300 };
301
302
211 // A contiguous address region that holds code. Each CodeRegion has a "kind" 303 // A contiguous address region that holds code. Each CodeRegion has a "kind"
212 // which describes the type of code contained inside the region. Each 304 // which describes the type of code contained inside the region. Each
213 // region covers the following interval: [start, end). 305 // region covers the following interval: [start, end).
214 class CodeRegion : public ZoneAllocated { 306 class CodeRegion : public ZoneAllocated {
215 public: 307 public:
216 enum Kind { 308 enum Kind {
217 kDartCode, // Live Dart code. 309 kDartCode, // Live Dart code.
218 kCollectedCode, // Dead Dart code. 310 kCollectedCode, // Dead Dart code.
219 kNativeCode, // Native code. 311 kNativeCode, // Native code.
220 kReusedCode, // Dead Dart code that has been reused by new kDartCode. 312 kReusedCode, // Dead Dart code that has been reused by new kDartCode.
221 kTagCode, // A special kind of code representing a tag. 313 kTagCode, // A special kind of code representing a tag.
222 }; 314 };
223 315
224 CodeRegion(Kind kind, uword start, uword end, int64_t timestamp) : 316 CodeRegion(Kind kind, uword start, uword end, int64_t timestamp)
225 kind_(kind), 317 : kind_(kind),
226 start_(start), 318 start_(start),
227 end_(end), 319 end_(end),
228 inclusive_ticks_(0), 320 inclusive_ticks_(0),
229 exclusive_ticks_(0), 321 exclusive_ticks_(0),
230 inclusive_tick_serial_(0), 322 inclusive_tick_serial_(0),
231 name_(NULL), 323 name_(NULL),
232 compile_timestamp_(timestamp), 324 compile_timestamp_(timestamp),
233 creation_serial_(0), 325 creation_serial_(0),
234 address_table_(new ZoneGrowableArray<AddressEntry>()), 326 address_table_(new ZoneGrowableArray<AddressEntry>()),
235 callers_table_(new ZoneGrowableArray<CallEntry>()), 327 callers_table_(new ZoneGrowableArray<CallEntry>()),
236 callees_table_(new ZoneGrowableArray<CallEntry>()) { 328 callees_table_(new ZoneGrowableArray<CallEntry>()) {
237 ASSERT(start_ < end_); 329 ASSERT(start_ < end_);
238 } 330 }
239 331
240 332
241 uword start() const { return start_; } 333 uword start() const { return start_; }
242 void set_start(uword start) { 334 void set_start(uword start) {
243 start_ = start; 335 start_ = start;
244 } 336 }
245 337
246 uword end() const { return end_; } 338 uword end() const { return end_; }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 if (exclusive) { 431 if (exclusive) {
340 exclusive_ticks_++; 432 exclusive_ticks_++;
341 } else { 433 } else {
342 inclusive_ticks_++; 434 inclusive_ticks_++;
343 // Mark the last serial we ticked the inclusive count. 435 // Mark the last serial we ticked the inclusive count.
344 inclusive_tick_serial_ = serial; 436 inclusive_tick_serial_ = serial;
345 } 437 }
346 TickAddress(pc, exclusive); 438 TickAddress(pc, exclusive);
347 } 439 }
348 440
349 void AddCaller(intptr_t index) { 441 void AddCaller(intptr_t index, intptr_t count) {
350 AddCallEntry(callers_table_, index); 442 AddCallEntry(callers_table_, index, count);
351 } 443 }
352 444
353 void AddCallee(intptr_t index) { 445 void AddCallee(intptr_t index, intptr_t count) {
354 AddCallEntry(callees_table_, index); 446 AddCallEntry(callees_table_, index, count);
355 } 447 }
356 448
357 void PrintNativeCode(JSONObject* profile_code_obj) { 449 void PrintNativeCode(JSONObject* profile_code_obj) {
358 ASSERT(kind() == kNativeCode); 450 ASSERT(kind() == kNativeCode);
359 JSONObject obj(profile_code_obj, "code"); 451 JSONObject obj(profile_code_obj, "code");
360 obj.AddProperty("type", "@Code"); 452 obj.AddProperty("type", "@Code");
361 obj.AddProperty("kind", "Native"); 453 obj.AddProperty("kind", "Native");
362 obj.AddProperty("name", name()); 454 obj.AddProperty("name", name());
363 obj.AddProperty("user_name", name()); 455 obj.AddProperty("user_name", name());
364 obj.AddPropertyF("start", "%" Px "", start()); 456 obj.AddPropertyF("start", "%" Px "", start());
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 // Generate a fake function entry. 502 // Generate a fake function entry.
411 JSONObject func(&obj, "function"); 503 JSONObject func(&obj, "function");
412 func.AddProperty("type", "@Function"); 504 func.AddProperty("type", "@Function");
413 obj.AddPropertyF("id", "functions/reused-%" Px "", start()); 505 obj.AddPropertyF("id", "functions/reused-%" Px "", start());
414 func.AddProperty("name", name()); 506 func.AddProperty("name", name());
415 func.AddProperty("user_name", name()); 507 func.AddProperty("user_name", name());
416 func.AddProperty("kind", "Reused"); 508 func.AddProperty("kind", "Reused");
417 } 509 }
418 } 510 }
419 511
512 void PrintTagCode(JSONObject* profile_code_obj) {
513 ASSERT(kind() == kTagCode);
514 JSONObject obj(profile_code_obj, "code");
515 obj.AddProperty("type", "@Code");
516 obj.AddProperty("kind", "Tag");
517 obj.AddPropertyF("id", "code/tag-%" Px "", start());
518 obj.AddProperty("name", name());
519 obj.AddProperty("user_name", name());
520 obj.AddPropertyF("start", "%" Px "", start());
521 obj.AddPropertyF("end", "%" Px "", end());
522 {
523 // Generate a fake function entry.
524 JSONObject func(&obj, "function");
525 func.AddProperty("type", "@Function");
526 func.AddProperty("kind", "Tag");
527 obj.AddPropertyF("id", "functions/tag-%" Px "", start());
528 func.AddProperty("name", name());
529 func.AddProperty("user_name", name());
530 }
531 }
532
420 void PrintToJSONArray(Isolate* isolate, JSONArray* events, bool full) { 533 void PrintToJSONArray(Isolate* isolate, JSONArray* events, bool full) {
421 JSONObject obj(events); 534 JSONObject obj(events);
422 obj.AddProperty("type", "CodeRegion"); 535 obj.AddProperty("type", "CodeRegion");
423 obj.AddProperty("kind", KindToCString(kind())); 536 obj.AddProperty("kind", KindToCString(kind()));
424 obj.AddPropertyF("inclusive_ticks", "%" Pd "", inclusive_ticks()); 537 obj.AddPropertyF("inclusive_ticks", "%" Pd "", inclusive_ticks());
425 obj.AddPropertyF("exclusive_ticks", "%" Pd "", exclusive_ticks()); 538 obj.AddPropertyF("exclusive_ticks", "%" Pd "", exclusive_ticks());
426 if (kind() == kDartCode) { 539 if (kind() == kDartCode) {
427 // Look up code in Dart heap. 540 // Look up code in Dart heap.
428 Code& code = Code::Handle(isolate); 541 Code& code = Code::Handle(isolate);
429 code ^= Code::LookupCode(start()); 542 code ^= Code::LookupCode(start());
430 if (code.IsNull()) { 543 if (code.IsNull()) {
431 // Code is a stub in the Vm isolate. 544 // Code is a stub in the Vm isolate.
432 code ^= Code::LookupCodeInVmIsolate(start()); 545 code ^= Code::LookupCodeInVmIsolate(start());
433 } 546 }
434 ASSERT(!code.IsNull()); 547 ASSERT(!code.IsNull());
435 obj.AddProperty("code", code, !full); 548 obj.AddProperty("code", code, !full);
436 } else if (kind() == kCollectedCode) { 549 } else if (kind() == kCollectedCode) {
437 if (name() == NULL) { 550 if (name() == NULL) {
438 // Lazily set generated name. 551 // Lazily set generated name.
439 GenerateAndSetSymbolName("[Collected]"); 552 GenerateAndSetSymbolName("[Collected]");
440 } 553 }
441 PrintCollectedCode(&obj); 554 PrintCollectedCode(&obj);
442 } else if (kind() == kReusedCode) { 555 } else if (kind() == kReusedCode) {
443 if (name() == NULL) { 556 if (name() == NULL) {
444 // Lazily set generated name. 557 // Lazily set generated name.
445 GenerateAndSetSymbolName("[Reused]"); 558 GenerateAndSetSymbolName("[Reused]");
446 } 559 }
447 PrintOverwrittenCode(&obj); 560 PrintOverwrittenCode(&obj);
561 } else if (kind() == kTagCode) {
562 if (name() == NULL) {
563 const char* tag_name = start() == 0 ? "root" : VMTag::TagName(start());
564 ASSERT(tag_name != NULL);
565 SetName(tag_name);
566 }
567 PrintTagCode(&obj);
448 } else { 568 } else {
449 ASSERT(kind() == kNativeCode); 569 ASSERT(kind() == kNativeCode);
450 if (name() == NULL) { 570 if (name() == NULL) {
451 // Lazily set generated name. 571 // Lazily set generated name.
452 GenerateAndSetSymbolName("[Native]"); 572 GenerateAndSetSymbolName("[Native]");
453 } 573 }
454 PrintNativeCode(&obj); 574 PrintNativeCode(&obj);
455 } 575 }
456 { 576 {
457 JSONArray ticks(&obj, "ticks"); 577 JSONArray ticks(&obj, "ticks");
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 if (i < length) { 624 if (i < length) {
505 // Insert at i. 625 // Insert at i.
506 address_table_->InsertAt(i, entry); 626 address_table_->InsertAt(i, entry);
507 } else { 627 } else {
508 // Add to end. 628 // Add to end.
509 address_table_->Add(entry); 629 address_table_->Add(entry);
510 } 630 }
511 } 631 }
512 632
513 633
514 void AddCallEntry(ZoneGrowableArray<CallEntry>* table, intptr_t index) { 634 void AddCallEntry(ZoneGrowableArray<CallEntry>* table, intptr_t index,
635 intptr_t count) {
515 const intptr_t length = table->length(); 636 const intptr_t length = table->length();
516 intptr_t i = 0; 637 intptr_t i = 0;
517 for (; i < length; i++) { 638 for (; i < length; i++) {
518 CallEntry& entry = (*table)[i]; 639 CallEntry& entry = (*table)[i];
519 if (entry.code_table_index == index) { 640 if (entry.code_table_index == index) {
520 entry.count++; 641 entry.count += count;
521 return; 642 return;
522 } 643 }
523 if (entry.code_table_index > index) { 644 if (entry.code_table_index > index) {
524 break; 645 break;
525 } 646 }
526 } 647 }
527 CallEntry entry; 648 CallEntry entry;
528 entry.code_table_index = index; 649 entry.code_table_index = index;
529 entry.count = 1; 650 entry.count = count;
530 if (i < length) { 651 if (i < length) {
531 table->InsertAt(i, entry); 652 table->InsertAt(i, entry);
532 } else { 653 } else {
533 table->Add(entry); 654 table->Add(entry);
534 } 655 }
535 } 656 }
536 657
537 void GenerateAndSetSymbolName(const char* prefix) { 658 void GenerateAndSetSymbolName(const char* prefix) {
538 const intptr_t kBuffSize = 512; 659 const intptr_t kBuffSize = 512;
539 char buff[kBuffSize]; 660 char buff[kBuffSize];
(...skipping 20 matching lines...) Expand all
560 // The compilation timestamp associated with this code region. 681 // The compilation timestamp associated with this code region.
561 int64_t compile_timestamp_; 682 int64_t compile_timestamp_;
562 // Serial number at which this CodeRegion was created. 683 // Serial number at which this CodeRegion was created.
563 intptr_t creation_serial_; 684 intptr_t creation_serial_;
564 ZoneGrowableArray<AddressEntry>* address_table_; 685 ZoneGrowableArray<AddressEntry>* address_table_;
565 ZoneGrowableArray<CallEntry>* callers_table_; 686 ZoneGrowableArray<CallEntry>* callers_table_;
566 ZoneGrowableArray<CallEntry>* callees_table_; 687 ZoneGrowableArray<CallEntry>* callees_table_;
567 DISALLOW_COPY_AND_ASSIGN(CodeRegion); 688 DISALLOW_COPY_AND_ASSIGN(CodeRegion);
568 }; 689 };
569 690
691
570 // A sorted table of CodeRegions. Does not allow for overlap. 692 // A sorted table of CodeRegions. Does not allow for overlap.
571 class CodeRegionTable : public ValueObject { 693 class CodeRegionTable : public ValueObject {
572 public: 694 public:
573 enum TickResult { 695 enum TickResult {
574 kTicked = 0, // CodeRegion found and ticked. 696 kTicked = 0, // CodeRegion found and ticked.
575 kNotFound = -1, // No CodeRegion found. 697 kNotFound = -1, // No CodeRegion found.
576 kNewerCode = -2, // CodeRegion found but it was compiled after sample. 698 kNewerCode = -2, // CodeRegion found but it was compiled after sample.
577 }; 699 };
578 700
579 CodeRegionTable() : 701 CodeRegionTable() :
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 } 844 }
723 845
724 static bool CompareLowerBound(uword pc, uword start, uword end) { 846 static bool CompareLowerBound(uword pc, uword start, uword end) {
725 return end <= pc; 847 return end <= pc;
726 } 848 }
727 849
728 void HandleOverlap(CodeRegion* region, CodeRegion* code_region, 850 void HandleOverlap(CodeRegion* region, CodeRegion* code_region,
729 uword start, uword end) { 851 uword start, uword end) {
730 // We should never see overlapping Dart code regions. 852 // We should never see overlapping Dart code regions.
731 ASSERT(region->kind() != CodeRegion::kDartCode); 853 ASSERT(region->kind() != CodeRegion::kDartCode);
854 // We should never see overlapping Tag code regions.
855 ASSERT(region->kind() != CodeRegion::kTagCode);
732 // When code regions overlap, they should be of the same kind. 856 // When code regions overlap, they should be of the same kind.
733 ASSERT(region->kind() == code_region->kind()); 857 ASSERT(region->kind() == code_region->kind());
734 region->AdjustExtent(start, end); 858 region->AdjustExtent(start, end);
735 } 859 }
736 860
737 #if defined(DEBUG) 861 #if defined(DEBUG)
738 void VerifyOrder() { 862 void VerifyOrder() {
739 const intptr_t length = code_region_table_->length(); 863 const intptr_t length = code_region_table_->length();
740 if (length == 0) { 864 if (length == 0) {
741 return; 865 return;
(...skipping 22 matching lines...) Expand all
764 #endif 888 #endif
765 889
766 ZoneGrowableArray<CodeRegion*>* code_region_table_; 890 ZoneGrowableArray<CodeRegion*>* code_region_table_;
767 }; 891 };
768 892
769 893
770 class CodeRegionTableBuilder : public SampleVisitor { 894 class CodeRegionTableBuilder : public SampleVisitor {
771 public: 895 public:
772 CodeRegionTableBuilder(Isolate* isolate, 896 CodeRegionTableBuilder(Isolate* isolate,
773 CodeRegionTable* live_code_table, 897 CodeRegionTable* live_code_table,
774 CodeRegionTable* dead_code_table) 898 CodeRegionTable* dead_code_table,
899 CodeRegionTable* tag_code_table)
775 : SampleVisitor(isolate), 900 : SampleVisitor(isolate),
776 live_code_table_(live_code_table), 901 live_code_table_(live_code_table),
777 dead_code_table_(dead_code_table), 902 dead_code_table_(dead_code_table),
903 tag_code_table_(tag_code_table),
778 isolate_(isolate), 904 isolate_(isolate),
779 vm_isolate_(Dart::vm_isolate()) { 905 vm_isolate_(Dart::vm_isolate()) {
780 ASSERT(live_code_table_ != NULL); 906 ASSERT(live_code_table_ != NULL);
781 ASSERT(dead_code_table_ != NULL); 907 ASSERT(dead_code_table_ != NULL);
908 ASSERT(tag_code_table_ != NULL);
782 frames_ = 0; 909 frames_ = 0;
783 min_time_ = kMaxInt64; 910 min_time_ = kMaxInt64;
784 max_time_ = 0; 911 max_time_ = 0;
785 ASSERT(isolate_ != NULL); 912 ASSERT(isolate_ != NULL);
786 ASSERT(vm_isolate_ != NULL); 913 ASSERT(vm_isolate_ != NULL);
787 } 914 }
788 915
789 void VisitSample(Sample* sample) { 916 void VisitSample(Sample* sample) {
790 int64_t timestamp = sample->timestamp(); 917 int64_t timestamp = sample->timestamp();
791 if (timestamp > max_time_) { 918 if (timestamp > max_time_) {
792 max_time_ = timestamp; 919 max_time_ = timestamp;
793 } 920 }
794 if (timestamp < min_time_) { 921 if (timestamp < min_time_) {
795 min_time_ = timestamp; 922 min_time_ = timestamp;
796 } 923 }
924 // Make sure VM tag is created.
925 CreateTag(sample->vm_tag());
797 // Exclusive tick for bottom frame. 926 // Exclusive tick for bottom frame.
798 Tick(sample->At(0), true, timestamp); 927 Tick(sample->At(0), true, timestamp);
799 // Inclusive tick for all frames. 928 // Inclusive tick for all frames.
800 for (intptr_t i = 0; i < FLAG_profile_depth; i++) { 929 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
801 if (sample->At(i) == 0) { 930 if (sample->At(i) == 0) {
802 break; 931 break;
803 } 932 }
804 frames_++; 933 frames_++;
805 Tick(sample->At(i), false, timestamp); 934 Tick(sample->At(i), false, timestamp);
806 } 935 }
807 } 936 }
808 937
809 intptr_t frames() const { return frames_; } 938 intptr_t frames() const { return frames_; }
810 939
811 intptr_t TimeDeltaMicros() const { 940 intptr_t TimeDeltaMicros() const {
812 return static_cast<intptr_t>(max_time_ - min_time_); 941 return static_cast<intptr_t>(max_time_ - min_time_);
813 } 942 }
814 int64_t max_time() const { return max_time_; } 943 int64_t max_time() const { return max_time_; }
815 944
816 private: 945 private:
946 void CreateTag(uword tag) {
947 intptr_t index = tag_code_table_->FindIndex(tag);
948 if (index >= 0) {
949 // Already created.
950 return;
951 }
952 CodeRegion* region = new CodeRegion(CodeRegion::kTagCode,
953 tag,
954 tag + 1,
955 0);
956 index = tag_code_table_->InsertCodeRegion(region);
957 ASSERT(index >= 0);
958 region->set_creation_serial(visited());
959 }
960
961 void TickTag(uword tag, bool exclusive) {
962 CodeRegionTable::TickResult r;
963 intptr_t serial = exclusive ? -1 : visited();
964 r = tag_code_table_->Tick(tag, exclusive, serial, 0);
965 if (r == CodeRegionTable::kTicked) {
966 // Live code found and ticked.
967 return;
968 }
969 ASSERT(r == CodeRegionTable::kNotFound);
970 CreateAndTickTagCodeRegion(tag, exclusive, serial);
971 }
972
973 void CreateAndTickTagCodeRegion(uword tag, bool exclusive, intptr_t serial) {
974 // Need to create tag code.
975 CodeRegion* region = new CodeRegion(CodeRegion::kTagCode,
976 tag,
977 tag + 1,
978 0);
979 intptr_t index = tag_code_table_->InsertCodeRegion(region);
980 region->set_creation_serial(visited());
981 ASSERT(index >= 0);
982 tag_code_table_->At(index)->Tick(tag, exclusive, serial);
983 }
984
817 void Tick(uword pc, bool exclusive, int64_t timestamp) { 985 void Tick(uword pc, bool exclusive, int64_t timestamp) {
818 CodeRegionTable::TickResult r; 986 CodeRegionTable::TickResult r;
819 intptr_t serial = exclusive ? -1 : visited(); 987 intptr_t serial = exclusive ? -1 : visited();
820 r = live_code_table_->Tick(pc, exclusive, serial, timestamp); 988 r = live_code_table_->Tick(pc, exclusive, serial, timestamp);
821 if (r == CodeRegionTable::kTicked) { 989 if (r == CodeRegionTable::kTicked) {
822 // Live code found and ticked. 990 // Live code found and ticked.
823 return; 991 return;
824 } 992 }
825 if (r == CodeRegionTable::kNewerCode) { 993 if (r == CodeRegionTable::kNewerCode) {
826 // Code has been overwritten by newer code. 994 // Code has been overwritten by newer code.
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 code_region->SetName(native_name); 1074 code_region->SetName(native_name);
907 free(native_name); 1075 free(native_name);
908 return code_region; 1076 return code_region;
909 } 1077 }
910 1078
911 intptr_t frames_; 1079 intptr_t frames_;
912 int64_t min_time_; 1080 int64_t min_time_;
913 int64_t max_time_; 1081 int64_t max_time_;
914 CodeRegionTable* live_code_table_; 1082 CodeRegionTable* live_code_table_;
915 CodeRegionTable* dead_code_table_; 1083 CodeRegionTable* dead_code_table_;
1084 CodeRegionTable* tag_code_table_;
916 Isolate* isolate_; 1085 Isolate* isolate_;
917 Isolate* vm_isolate_; 1086 Isolate* vm_isolate_;
918 }; 1087 };
919 1088
920 1089
921 class CodeRegionTableCallersBuilder : public SampleVisitor { 1090 class CodeRegionExclusiveTrieBuilder : public SampleVisitor {
922 public: 1091 public:
923 CodeRegionTableCallersBuilder(Isolate* isolate, 1092 CodeRegionExclusiveTrieBuilder(Isolate* isolate,
924 CodeRegionTable* live_code_table, 1093 CodeRegionTable* live_code_table,
925 CodeRegionTable* dead_code_table) 1094 CodeRegionTable* dead_code_table,
1095 CodeRegionTable* tag_code_table)
926 : SampleVisitor(isolate), 1096 : SampleVisitor(isolate),
927 live_code_table_(live_code_table), 1097 live_code_table_(live_code_table),
928 dead_code_table_(dead_code_table) { 1098 dead_code_table_(dead_code_table),
1099 tag_code_table_(tag_code_table) {
929 ASSERT(live_code_table_ != NULL); 1100 ASSERT(live_code_table_ != NULL);
930 ASSERT(dead_code_table_ != NULL); 1101 ASSERT(dead_code_table_ != NULL);
1102 ASSERT(tag_code_table_ != NULL);
931 dead_code_table_offset_ = live_code_table_->Length(); 1103 dead_code_table_offset_ = live_code_table_->Length();
1104 tag_code_table_offset_ = dead_code_table_offset_ +
1105 dead_code_table_->Length();
1106 intptr_t root_index = tag_code_table_->FindIndex(0);
1107 // Verify that the "0" tag does not exist.
1108 ASSERT(root_index < 0);
1109 // Insert the dummy tag CodeRegion that is used for the Trie root.
1110 CodeRegion* region = new CodeRegion(CodeRegion::kTagCode, 0, 1, 0);
1111 root_index = tag_code_table_->InsertCodeRegion(region);
1112 ASSERT(root_index >= 0);
1113 region->set_creation_serial(0);
1114 root_ = new CodeRegionTrieNode(tag_code_table_offset_ + root_index);
1115 // Use tags by default.
1116 set_use_tags(true);
932 } 1117 }
933 1118
934 void VisitSample(Sample* sample) { 1119 void VisitSample(Sample* sample) {
935 int64_t timestamp = sample->timestamp(); 1120 // Give the root a tick.
936 intptr_t current_index = FindFinalIndex(sample->At(0), timestamp); 1121 root_->Tick();
937 ASSERT(current_index >= 0); 1122 CodeRegionTrieNode* current = root_;
938 CodeRegion* current = At(current_index); 1123 if (use_tags()) {
939 intptr_t caller_index = -1; 1124 intptr_t tag_index = FindTagIndex(sample->vm_tag());
940 CodeRegion* caller = NULL; 1125 current = current->GetChild(tag_index);
941 intptr_t callee_index = -1; 1126 // Give the tag a tick.
942 CodeRegion* callee = NULL; 1127 current->Tick();
943 for (intptr_t i = 1; i < FLAG_profile_depth; i++) { 1128 }
1129 // Walk the sampled PCs.
1130 for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
944 if (sample->At(i) == 0) { 1131 if (sample->At(i) == 0) {
945 break; 1132 break;
946 } 1133 }
947 caller_index = FindFinalIndex(sample->At(i), timestamp); 1134 intptr_t index = FindFinalIndex(sample->At(i), sample->timestamp());
948 ASSERT(caller_index >= 0); 1135 current = current->GetChild(index);
949 caller = At(caller_index); 1136 current->Tick();
950 current->AddCaller(caller_index);
951 if (callee != NULL) {
952 current->AddCallee(callee_index);
953 }
954 // Move cursors.
955 callee_index = current_index;
956 callee = current;
957 current_index = caller_index;
958 current = caller;
959 } 1137 }
960 } 1138 }
961 1139
1140 CodeRegionTrieNode* root() const {
1141 return root_;
1142 }
1143
1144 bool use_tags() const {
1145 return use_tags_;
1146 }
1147
1148 void set_use_tags(bool use_tags) {
1149 use_tags_ = use_tags;
1150 }
1151
962 private: 1152 private:
1153 intptr_t FindTagIndex(uword tag) const {
1154 intptr_t index = tag_code_table_->FindIndex(tag);
1155 ASSERT(index >= 0);
1156 CodeRegion* region = tag_code_table_->At(index);
1157 ASSERT(region->contains(tag));
siva 2014/03/18 00:05:20 Can this be: ASSERT((tag_code_table_->At(index))->
Cutch 2014/03/18 14:39:19 Done.
1158 return tag_code_table_offset_ + index;
1159 }
1160
963 intptr_t FindFinalIndex(uword pc, int64_t timestamp) const { 1161 intptr_t FindFinalIndex(uword pc, int64_t timestamp) const {
964 intptr_t index = live_code_table_->FindIndex(pc); 1162 intptr_t index = live_code_table_->FindIndex(pc);
965 ASSERT(index >= 0); 1163 ASSERT(index >= 0);
966 CodeRegion* region = live_code_table_->At(index); 1164 CodeRegion* region = live_code_table_->At(index);
967 ASSERT(region->contains(pc)); 1165 ASSERT(region->contains(pc));
968 if (region->compile_timestamp() > timestamp) { 1166 if (region->compile_timestamp() > timestamp) {
969 // Overwritten code, find in dead code table. 1167 // Overwritten code, find in dead code table.
970 index = dead_code_table_->FindIndex(pc); 1168 index = dead_code_table_->FindIndex(pc);
971 ASSERT(index >= 0); 1169 ASSERT(index >= 0);
972 region = dead_code_table_->At(index); 1170 region = dead_code_table_->At(index);
973 ASSERT(region->contains(pc)); 1171 ASSERT(region->contains(pc));
974 ASSERT(region->compile_timestamp() <= timestamp); 1172 ASSERT(region->compile_timestamp() <= timestamp);
975 return index + dead_code_table_offset_; 1173 return index + dead_code_table_offset_;
976 } 1174 }
977 ASSERT(region->compile_timestamp() <= timestamp); 1175 ASSERT(region->compile_timestamp() <= timestamp);
978 return index; 1176 return index;
979 } 1177 }
980 1178
1179 bool use_tags_;
1180 CodeRegionTrieNode* root_;
1181 CodeRegionTable* live_code_table_;
1182 CodeRegionTable* dead_code_table_;
1183 CodeRegionTable* tag_code_table_;
1184 intptr_t dead_code_table_offset_;
1185 intptr_t tag_code_table_offset_;
1186 };
1187
1188
1189 class CodeRegionTableCallersBuilder {
1190 public:
1191 CodeRegionTableCallersBuilder(CodeRegionTrieNode* exclusive_root,
1192 CodeRegionTable* live_code_table,
1193 CodeRegionTable* dead_code_table,
1194 CodeRegionTable* tag_code_table)
1195 : exclusive_root_(exclusive_root),
1196 live_code_table_(live_code_table),
1197 dead_code_table_(dead_code_table),
1198 tag_code_table_(tag_code_table) {
1199 ASSERT(exclusive_root_ != NULL);
1200 ASSERT(live_code_table_ != NULL);
1201 ASSERT(dead_code_table_ != NULL);
1202 ASSERT(tag_code_table_ != NULL);
1203 dead_code_table_offset_ = live_code_table_->Length();
1204 tag_code_table_offset_ = dead_code_table_offset_ +
1205 dead_code_table_->Length();
1206 }
1207
1208 void Build() {
1209 ProcessNode(exclusive_root_);
1210 }
1211
1212 private:
1213 void ProcessNode(CodeRegionTrieNode* parent) {
1214 const ZoneGrowableArray<CodeRegionTrieNode*>& children = parent->children();
1215 intptr_t parent_index = parent->code_region_index();
1216 ASSERT(parent_index >= 0);
1217 CodeRegion* parent_region = At(parent_index);
1218 ASSERT(parent_region != NULL);
1219 for (intptr_t i = 0; i < children.length(); i++) {
1220 CodeRegionTrieNode* node = children[i];
1221 ProcessNode(node);
1222 intptr_t index = node->code_region_index();
1223 ASSERT(index >= 0);
1224 CodeRegion* region = At(index);
1225 ASSERT(region != NULL);
1226 region->AddCallee(parent_index, node->count());
1227 parent_region->AddCaller(index, node->count());
1228 }
1229 }
1230
981 CodeRegion* At(intptr_t final_index) { 1231 CodeRegion* At(intptr_t final_index) {
982 ASSERT(final_index >= 0); 1232 ASSERT(final_index >= 0);
983 if (final_index < dead_code_table_offset_) { 1233 if (final_index < dead_code_table_offset_) {
984 return live_code_table_->At(final_index); 1234 return live_code_table_->At(final_index);
1235 } else if (final_index < tag_code_table_offset_) {
1236 return dead_code_table_->At(final_index - dead_code_table_offset_);
985 } else { 1237 } else {
986 return dead_code_table_->At(final_index - dead_code_table_offset_); 1238 return tag_code_table_->At(final_index - tag_code_table_offset_);
987 } 1239 }
988 } 1240 }
989 1241
1242 CodeRegionTrieNode* exclusive_root_;
990 CodeRegionTable* live_code_table_; 1243 CodeRegionTable* live_code_table_;
991 CodeRegionTable* dead_code_table_; 1244 CodeRegionTable* dead_code_table_;
1245 CodeRegionTable* tag_code_table_;
992 intptr_t dead_code_table_offset_; 1246 intptr_t dead_code_table_offset_;
1247 intptr_t tag_code_table_offset_;
993 }; 1248 };
994 1249
1250
995 void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream, 1251 void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream,
996 bool full) { 1252 bool full, bool use_tags) {
997 ASSERT(isolate == Isolate::Current()); 1253 ASSERT(isolate == Isolate::Current());
998 // Disable profile interrupts while processing the buffer. 1254 // Disable profile interrupts while processing the buffer.
999 EndExecution(isolate); 1255 EndExecution(isolate);
1000 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); 1256 MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
1001 IsolateProfilerData* profiler_data = isolate->profiler_data(); 1257 IsolateProfilerData* profiler_data = isolate->profiler_data();
1002 if (profiler_data == NULL) { 1258 if (profiler_data == NULL) {
1003 JSONObject error(stream); 1259 JSONObject error(stream);
1004 error.AddProperty("type", "Error"); 1260 error.AddProperty("type", "Error");
1005 error.AddProperty("text", "Isolate does not have profiling enabled."); 1261 error.AddProperty("text", "Isolate does not have profiling enabled.");
1006 return; 1262 return;
1007 } 1263 }
1008 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); 1264 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
1009 ASSERT(sample_buffer != NULL); 1265 ASSERT(sample_buffer != NULL);
1010 { 1266 {
1011 StackZone zone(isolate); 1267 StackZone zone(isolate);
1012 { 1268 {
1013 // Live code holds Dart, Native, and Collected CodeRegions. 1269 // Live code holds Dart, Native, and Collected CodeRegions.
1014 CodeRegionTable live_code_table; 1270 CodeRegionTable live_code_table;
1015 // Dead code holds Overwritten CodeRegions. 1271 // Dead code holds Overwritten CodeRegions.
1016 CodeRegionTable dead_code_table; 1272 CodeRegionTable dead_code_table;
1273 // Tag code holds Tag CodeRegions.
1274 CodeRegionTable tag_code_table;
1017 CodeRegionTableBuilder builder(isolate, 1275 CodeRegionTableBuilder builder(isolate,
1018 &live_code_table, 1276 &live_code_table,
1019 &dead_code_table); 1277 &dead_code_table,
1278 &tag_code_table);
1020 { 1279 {
1021 // Build CodeRegion tables. 1280 // Build CodeRegion tables.
1022 ScopeStopwatch sw("CodeTableBuild"); 1281 ScopeStopwatch sw("CodeRegionTableBuilder");
1023 sample_buffer->VisitSamples(&builder); 1282 sample_buffer->VisitSamples(&builder);
1024 } 1283 }
1025 intptr_t samples = builder.visited(); 1284 intptr_t samples = builder.visited();
1026 intptr_t frames = builder.frames(); 1285 intptr_t frames = builder.frames();
1027 if (FLAG_trace_profiled_isolates) { 1286 if (FLAG_trace_profiled_isolates) {
1028 intptr_t total_live_code_objects = live_code_table.Length(); 1287 intptr_t total_live_code_objects = live_code_table.Length();
1029 intptr_t total_dead_code_objects = dead_code_table.Length(); 1288 intptr_t total_dead_code_objects = dead_code_table.Length();
1289 intptr_t total_tag_code_objects = tag_code_table.Length();
1030 OS::Print("Processed %" Pd " frames\n", frames); 1290 OS::Print("Processed %" Pd " frames\n", frames);
1031 OS::Print("CodeTables: live=%" Pd " dead=%" Pd "\n", 1291 OS::Print("CodeTables: live=%" Pd " dead=%" Pd " tag=%" Pd "\n",
1032 total_live_code_objects, 1292 total_live_code_objects,
1033 total_dead_code_objects); 1293 total_dead_code_objects,
1294 total_tag_code_objects);
1034 } 1295 }
1035 #if defined(DEBUG) 1296 #if defined(DEBUG)
1036 live_code_table.Verify(); 1297 live_code_table.Verify();
1037 dead_code_table.Verify(); 1298 dead_code_table.Verify();
1299 tag_code_table.Verify();
1038 if (FLAG_trace_profiled_isolates) { 1300 if (FLAG_trace_profiled_isolates) {
1039 OS::Print("CodeRegionTables verified to be ordered and not overlap.\n"); 1301 OS::Print("CodeRegionTables verified to be ordered and not overlap.\n");
1040 } 1302 }
1041 #endif 1303 #endif
1042 CodeRegionTableCallersBuilder build_callers(isolate, 1304 CodeRegionExclusiveTrieBuilder build_trie(isolate,
1305 &live_code_table,
1306 &dead_code_table,
1307 &tag_code_table);
1308 build_trie.set_use_tags(use_tags);
1309 {
1310 // Build CodeRegion trie.
1311 ScopeStopwatch sw("CodeRegionExclusiveTrieBuilder");
1312 sample_buffer->VisitSamples(&build_trie);
1313 build_trie.root()->RecursiveSort();
1314 }
1315 CodeRegionTableCallersBuilder build_callers(build_trie.root(),
1043 &live_code_table, 1316 &live_code_table,
1044 &dead_code_table); 1317 &dead_code_table,
1318 &tag_code_table);
1045 { 1319 {
1046 // Build CodeRegion callers. 1320 // Build CodeRegion callers.
1047 ScopeStopwatch sw("CodeTableCallersBuild"); 1321 ScopeStopwatch sw("CodeRegionTableCallersBuilder");
1048 sample_buffer->VisitSamples(&build_callers); 1322 build_callers.Build();
1049 } 1323 }
1050 { 1324 {
1051 ScopeStopwatch sw("CodeTableStream"); 1325 ScopeStopwatch sw("CodeTableStream");
1052 // Serialize to JSON. 1326 // Serialize to JSON.
1053 JSONObject obj(stream); 1327 JSONObject obj(stream);
1054 obj.AddProperty("type", "Profile"); 1328 obj.AddProperty("type", "Profile");
1055 obj.AddProperty("id", "profile"); 1329 obj.AddProperty("id", "profile");
1056 obj.AddProperty("samples", samples); 1330 obj.AddProperty("samples", samples);
1331 obj.AddProperty("depth", static_cast<intptr_t>(FLAG_profile_depth));
1332 obj.AddProperty("period", static_cast<intptr_t>(FLAG_profile_period));
1057 obj.AddProperty("time_delta_micros", builder.TimeDeltaMicros()); 1333 obj.AddProperty("time_delta_micros", builder.TimeDeltaMicros());
1334 {
1335 JSONArray exclusive_trie(&obj, "exclusive_trie");
1336 CodeRegionTrieNode* root = build_trie.root();
1337 ASSERT(root != NULL);
1338 root->PrintToJSONArray(&exclusive_trie);
1339 }
1058 JSONArray codes(&obj, "codes"); 1340 JSONArray codes(&obj, "codes");
1059 for (intptr_t i = 0; i < live_code_table.Length(); i++) { 1341 for (intptr_t i = 0; i < live_code_table.Length(); i++) {
1060 CodeRegion* region = live_code_table.At(i); 1342 CodeRegion* region = live_code_table.At(i);
1061 ASSERT(region != NULL); 1343 ASSERT(region != NULL);
1062 region->PrintToJSONArray(isolate, &codes, full); 1344 region->PrintToJSONArray(isolate, &codes, full);
1063 } 1345 }
1064 for (intptr_t i = 0; i < dead_code_table.Length(); i++) { 1346 for (intptr_t i = 0; i < dead_code_table.Length(); i++) {
1065 CodeRegion* region = dead_code_table.At(i); 1347 CodeRegion* region = dead_code_table.At(i);
1066 ASSERT(region != NULL); 1348 ASSERT(region != NULL);
1067 region->PrintToJSONArray(isolate, &codes, full); 1349 region->PrintToJSONArray(isolate, &codes, full);
1068 } 1350 }
1351 for (intptr_t i = 0; i < tag_code_table.Length(); i++) {
1352 CodeRegion* region = tag_code_table.At(i);
1353 ASSERT(region != NULL);
1354 region->PrintToJSONArray(isolate, &codes, full);
1355 }
1069 } 1356 }
1070 } 1357 }
1071 } 1358 }
1072 // Enable profile interrupts. 1359 // Enable profile interrupts.
1073 BeginExecution(isolate); 1360 BeginExecution(isolate);
1074 } 1361 }
1075 1362
1076 1363
1077 void Profiler::WriteProfile(Isolate* isolate) { 1364 void Profiler::WriteProfile(Isolate* isolate) {
1078 if (isolate == NULL) { 1365 if (isolate == NULL) {
(...skipping 10 matching lines...) Expand all
1089 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); 1376 Dart_FileCloseCallback file_close = Isolate::file_close_callback();
1090 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); 1377 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
1091 if ((file_open == NULL) || (file_close == NULL) || (file_write == NULL)) { 1378 if ((file_open == NULL) || (file_close == NULL) || (file_write == NULL)) {
1092 // Embedder has not provided necessary callbacks. 1379 // Embedder has not provided necessary callbacks.
1093 return; 1380 return;
1094 } 1381 }
1095 // We will be looking up code objects within the isolate. 1382 // We will be looking up code objects within the isolate.
1096 ASSERT(Isolate::Current() == isolate); 1383 ASSERT(Isolate::Current() == isolate);
1097 JSONStream stream(10 * MB); 1384 JSONStream stream(10 * MB);
1098 intptr_t pid = OS::ProcessId(); 1385 intptr_t pid = OS::ProcessId();
1099 PrintToJSONStream(isolate, &stream, true); 1386 PrintToJSONStream(isolate, &stream, true, false);
1100 const char* format = "%s/dart-profile-%" Pd "-%" Pd ".json"; 1387 const char* format = "%s/dart-profile-%" Pd "-%" Pd ".json";
1101 intptr_t len = OS::SNPrint(NULL, 0, format, 1388 intptr_t len = OS::SNPrint(NULL, 0, format,
1102 FLAG_profile_dir, pid, isolate->main_port()); 1389 FLAG_profile_dir, pid, isolate->main_port());
1103 char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 1390 char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
1104 OS::SNPrint(filename, len + 1, format, 1391 OS::SNPrint(filename, len + 1, format,
1105 FLAG_profile_dir, pid, isolate->main_port()); 1392 FLAG_profile_dir, pid, isolate->main_port());
1106 void* f = file_open(filename, true); 1393 void* f = file_open(filename, true);
1107 if (f == NULL) { 1394 if (f == NULL) {
1108 // Cannot write. 1395 // Cannot write.
1109 return; 1396 return;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 uword sp) 1445 uword sp)
1159 : sample_(sample), 1446 : sample_(sample),
1160 stack_upper_(stack_upper), 1447 stack_upper_(stack_upper),
1161 original_pc_(pc), 1448 original_pc_(pc),
1162 original_fp_(fp), 1449 original_fp_(fp),
1163 original_sp_(sp), 1450 original_sp_(sp),
1164 lower_bound_(stack_lower) { 1451 lower_bound_(stack_lower) {
1165 ASSERT(sample_ != NULL); 1452 ASSERT(sample_ != NULL);
1166 } 1453 }
1167 1454
1168 int walk(Heap* heap) { 1455 int walk(Heap* heap, uword vm_tag) {
1169 const intptr_t kMaxStep = 0x1000; // 4K. 1456 const intptr_t kMaxStep = 0x1000; // 4K.
1170 const bool kWalkStack = true; // Walk the stack. 1457 const bool kWalkStack = true; // Walk the stack.
1171 // Always store the exclusive PC. 1458 // Always store the exclusive PC.
1172 sample_->SetAt(0, original_pc_); 1459 sample_->SetAt(0, original_pc_);
1460 // Always store the vm tag.
1461 sample_->set_vm_tag(vm_tag);
1173 if (!kWalkStack) { 1462 if (!kWalkStack) {
1174 // Not walking the stack, only took exclusive sample. 1463 // Not walking the stack, only took exclusive sample.
1175 return 1; 1464 return 1;
1176 } 1465 }
1177 uword* pc = reinterpret_cast<uword*>(original_pc_); 1466 uword* pc = reinterpret_cast<uword*>(original_pc_);
1178 uword* fp = reinterpret_cast<uword*>(original_fp_); 1467 uword* fp = reinterpret_cast<uword*>(original_fp_);
1179 uword* previous_fp = fp; 1468 uword* previous_fp = fp;
1180 if (original_sp_ > original_fp_) { 1469 if (original_sp_ > original_fp_) {
1181 // Stack pointer should not be above frame pointer. 1470 // Stack pointer should not be above frame pointer.
1182 return 1; 1471 return 1;
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1280 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); 1569 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid);
1281 uword stack_lower = 0; 1570 uword stack_lower = 0;
1282 uword stack_upper = 0; 1571 uword stack_upper = 0;
1283 isolate->GetStackBounds(&stack_lower, &stack_upper); 1572 isolate->GetStackBounds(&stack_lower, &stack_upper);
1284 if ((stack_lower == 0) || (stack_upper == 0)) { 1573 if ((stack_lower == 0) || (stack_upper == 0)) {
1285 stack_lower = 0; 1574 stack_lower = 0;
1286 stack_upper = 0; 1575 stack_upper = 0;
1287 } 1576 }
1288 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, 1577 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper,
1289 state.pc, state.fp, state.sp); 1578 state.pc, state.fp, state.sp);
1290 stackWalker.walk(isolate->heap()); 1579 stackWalker.walk(isolate->heap(), isolate->vm_tag());
1291 } 1580 }
1292 1581
1293 1582
1294 } // namespace dart 1583 } // namespace dart
OLDNEW
« runtime/vm/object.cc ('K') | « runtime/vm/profiler.h ('k') | runtime/vm/service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698