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

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

Powered by Google App Engine
This is Rietveld 408576698