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

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

Issue 2680213002: Updated MallocHooks to collect stack traces when memory is allocated. (Closed)
Patch Set: Rough first patch Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« runtime/vm/profiler.h ('K') | « runtime/vm/profiler.h ('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/address_sanitizer.h" 5 #include "platform/address_sanitizer.h"
6 #include "platform/memory_sanitizer.h" 6 #include "platform/memory_sanitizer.h"
7 #include "platform/utils.h" 7 #include "platform/utils.h"
8 8
9 #include "vm/allocation.h" 9 #include "vm/allocation.h"
10 #include "vm/atomic.h" 10 #include "vm/atomic.h"
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc); 350 OS::PrintErr(" [0x%" Pp "] Unknown symbol\n", pc);
351 } else { 351 } else {
352 OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name); 352 OS::PrintErr(" [0x%" Pp "] %s\n", pc, native_symbol_name);
353 NativeSymbolResolver::FreeSymbolName(native_symbol_name); 353 NativeSymbolResolver::FreeSymbolName(native_symbol_name);
354 } 354 }
355 } 355 }
356 356
357 357
358 class ProfilerStackWalker : public ValueObject { 358 class ProfilerStackWalker : public ValueObject {
359 public: 359 public:
360 ProfilerStackWalker(Isolate* isolate, 360 ProfilerStackWalker(Dart_Port port_id,
361 Sample* head_sample, 361 Sample* head_sample,
362 SampleBuffer* sample_buffer) 362 SampleBuffer* sample_buffer)
363 : isolate_(isolate), 363 : port_id_(port_id),
364 sample_(head_sample), 364 sample_(head_sample),
365 sample_buffer_(sample_buffer), 365 sample_buffer_(sample_buffer),
366 frame_index_(0), 366 frame_index_(0),
367 total_frames_(0) { 367 total_frames_(0) {
368 ASSERT(isolate_ != NULL);
369 if (sample_ == NULL) { 368 if (sample_ == NULL) {
370 ASSERT(sample_buffer_ == NULL); 369 ASSERT(sample_buffer_ == NULL);
371 } else { 370 } else {
372 ASSERT(sample_buffer_ != NULL); 371 ASSERT(sample_buffer_ != NULL);
373 ASSERT(sample_->head_sample()); 372 ASSERT(sample_->head_sample());
374 } 373 }
375 } 374 }
376 375
377 bool Append(uword pc) { 376 bool Append(uword pc) {
378 if (sample_ == NULL) { 377 if (sample_ == NULL) {
(...skipping 18 matching lines...) Expand all
397 sample_ = new_sample; 396 sample_ = new_sample;
398 } 397 }
399 ASSERT(frame_index_ < kSampleSize); 398 ASSERT(frame_index_ < kSampleSize);
400 sample_->SetAt(frame_index_, pc); 399 sample_->SetAt(frame_index_, pc);
401 frame_index_++; 400 frame_index_++;
402 total_frames_++; 401 total_frames_++;
403 return true; 402 return true;
404 } 403 }
405 404
406 protected: 405 protected:
407 Isolate* isolate_; 406 Dart_Port port_id_;
408 Sample* sample_; 407 Sample* sample_;
409 SampleBuffer* sample_buffer_; 408 SampleBuffer* sample_buffer_;
410 intptr_t frame_index_; 409 intptr_t frame_index_;
411 intptr_t total_frames_; 410 intptr_t total_frames_;
412 }; 411 };
413 412
414 413
415 // Executing Dart code, walk the stack. 414 // Executing Dart code, walk the stack.
416 class ProfilerDartStackWalker : public ProfilerStackWalker { 415 class ProfilerDartStackWalker : public ProfilerStackWalker {
417 public: 416 public:
418 ProfilerDartStackWalker(Thread* thread, 417 ProfilerDartStackWalker(Thread* thread,
419 Sample* sample, 418 Sample* sample,
420 SampleBuffer* sample_buffer, 419 SampleBuffer* sample_buffer,
421 uword stack_lower, 420 uword stack_lower,
422 uword stack_upper, 421 uword stack_upper,
423 uword pc, 422 uword pc,
424 uword fp, 423 uword fp,
425 uword sp, 424 uword sp,
426 bool exited_dart_code, 425 bool exited_dart_code,
427 bool allocation_sample) 426 bool allocation_sample)
428 : ProfilerStackWalker(thread->isolate(), sample, sample_buffer), 427 : ProfilerStackWalker(thread->isolate() != NULL
Cutch 2017/02/08 00:28:54 Wrap comparison in parens: (thread->isolate() !=
bkonyi 2017/02/08 01:37:05 Done.
428 ? thread->isolate()->main_port()
429 : ILLEGAL_PORT,
430 sample,
431 sample_buffer),
429 pc_(reinterpret_cast<uword*>(pc)), 432 pc_(reinterpret_cast<uword*>(pc)),
430 fp_(reinterpret_cast<uword*>(fp)), 433 fp_(reinterpret_cast<uword*>(fp)),
431 sp_(reinterpret_cast<uword*>(sp)), 434 sp_(reinterpret_cast<uword*>(sp)),
432 stack_upper_(stack_upper), 435 stack_upper_(stack_upper),
433 stack_lower_(stack_lower), 436 stack_lower_(stack_lower),
434 has_exit_frame_(exited_dart_code) { 437 has_exit_frame_(exited_dart_code) {
435 if (exited_dart_code) { 438 if (exited_dart_code) {
436 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames, 439 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
437 thread); 440 thread);
438 pc_ = NULL; 441 pc_ = NULL;
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 bool has_exit_frame_; 593 bool has_exit_frame_;
591 }; 594 };
592 595
593 596
594 // If the VM is compiled without frame pointers (which is the default on 597 // If the VM is compiled without frame pointers (which is the default on
595 // recent GCC versions with optimizing enabled) the stack walking code may 598 // recent GCC versions with optimizing enabled) the stack walking code may
596 // fail. 599 // fail.
597 // 600 //
598 class ProfilerNativeStackWalker : public ProfilerStackWalker { 601 class ProfilerNativeStackWalker : public ProfilerStackWalker {
599 public: 602 public:
600 ProfilerNativeStackWalker(Isolate* isolate, 603 ProfilerNativeStackWalker(Dart_Port port_id,
601 Sample* sample, 604 Sample* sample,
602 SampleBuffer* sample_buffer, 605 SampleBuffer* sample_buffer,
603 uword stack_lower, 606 uword stack_lower,
604 uword stack_upper, 607 uword stack_upper,
605 uword pc, 608 uword pc,
606 uword fp, 609 uword fp,
607 uword sp) 610 uword sp)
608 : ProfilerStackWalker(isolate, sample, sample_buffer), 611 : ProfilerStackWalker(port_id, sample, sample_buffer),
609 stack_upper_(stack_upper), 612 stack_upper_(stack_upper),
610 original_pc_(pc), 613 original_pc_(pc),
611 original_fp_(fp), 614 original_fp_(fp),
612 original_sp_(sp), 615 original_sp_(sp),
613 lower_bound_(stack_lower) {} 616 lower_bound_(stack_lower) {}
614 617
615 void walk() { 618 void walk() {
616 const uword kMaxStep = VirtualMemory::PageSize(); 619 const uword kMaxStep = VirtualMemory::PageSize();
617 Append(original_pc_); 620 Append(original_pc_);
618 621
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 858
856 if ((fp < *stack_lower) || (fp >= *stack_upper)) { 859 if ((fp < *stack_lower) || (fp >= *stack_upper)) {
857 // Frame pointer is outside threads's stack boundary. 860 // Frame pointer is outside threads's stack boundary.
858 return false; 861 return false;
859 } 862 }
860 863
861 return true; 864 return true;
862 } 865 }
863 866
864 867
868 static bool GetAndValidateThreadStackBounds(OSThread* os_thread,
Cutch 2017/02/08 00:28:54 please find a way to merge this function with the
bkonyi 2017/02/08 01:37:05 Acknowledged. Will do this for patch 3.
bkonyi 2017/02/09 21:22:46 Done.
869 uintptr_t fp,
870 uintptr_t sp,
871 uword* stack_lower,
872 uword* stack_upper) {
873 ASSERT(os_thread != NULL);
874 ASSERT(stack_lower != NULL);
875 ASSERT(stack_upper != NULL);
876 if (!os_thread->GetProfilerStackBounds(stack_lower, stack_upper) ||
877 (*stack_lower == 0) || (*stack_upper == 0)) {
878 // Could not get stack boundary.
879 }
880
881 if (sp > *stack_lower) {
882 // The stack pointer gives us a tighter lower bound.
883 *stack_lower = sp;
884 }
885
886 if (*stack_lower >= *stack_upper) {
887 // Stack boundary is invalid.
888 return false;
889 }
890
891 if ((sp < *stack_lower) || (sp >= *stack_upper)) {
892 // Stack pointer is outside thread's stack boundary.
893 return false;
894 }
895
896 if ((fp < *stack_lower) || (fp >= *stack_upper)) {
897 // Frame pointer is outside threads's stack boundary.
898 return false;
899 }
900
901 return true;
902 }
903
904
865 // Some simple sanity checking of |pc|, |fp|, and |sp|. 905 // Some simple sanity checking of |pc|, |fp|, and |sp|.
866 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) { 906 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) {
867 if ((sp == 0) || (fp == 0) || (pc == 0)) { 907 if ((sp == 0) || (fp == 0) || (pc == 0)) {
868 // None of these registers should be zero. 908 // None of these registers should be zero.
869 return false; 909 return false;
870 } 910 }
871 911
872 if (sp > fp) { 912 if (sp > fp) {
873 // Assuming the stack grows down, we should never have a stack pointer above 913 // Assuming the stack grows down, we should never have a stack pointer above
874 // the frame pointer. 914 // the frame pointer.
875 return false; 915 return false;
876 } 916 }
877 917
878 return true; 918 return true;
879 } 919 }
880 920
881 921
882 static Sample* SetupSample(Thread* thread, 922 static Sample* SetupSample(Thread* thread,
883 SampleBuffer* sample_buffer, 923 SampleBuffer* sample_buffer,
884 ThreadId tid) { 924 ThreadId tid) {
885 ASSERT(thread != NULL); 925 ASSERT(thread != NULL);
886 Isolate* isolate = thread->isolate(); 926 Isolate* isolate = thread->isolate();
887 ASSERT(sample_buffer != NULL); 927 ASSERT(sample_buffer != NULL);
888 Sample* sample = sample_buffer->ReserveSample(); 928 Sample* sample = sample_buffer->ReserveSample();
889 sample->Init(isolate, OS::GetCurrentMonotonicMicros(), tid); 929 sample->Init(isolate, OS::GetCurrentMonotonicMicros(), tid);
Cutch 2017/02/08 00:28:54 As discussed: Sample needs to store the Dart_Port
890 uword vm_tag = thread->vm_tag(); 930 uword vm_tag = thread->vm_tag();
891 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC) 931 #if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
892 // When running in the simulator, the runtime entry function address 932 // When running in the simulator, the runtime entry function address
893 // (stored as the vm tag) is the address of a redirect function. 933 // (stored as the vm tag) is the address of a redirect function.
894 // Attempt to find the real runtime entry function address and use that. 934 // Attempt to find the real runtime entry function address and use that.
895 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); 935 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag);
896 if (redirect_vm_tag != 0) { 936 if (redirect_vm_tag != 0) {
897 vm_tag = redirect_vm_tag; 937 vm_tag = redirect_vm_tag;
898 } 938 }
899 #endif 939 #endif
900 sample->set_vm_tag(vm_tag); 940 sample->set_vm_tag(vm_tag);
901 sample->set_user_tag(isolate->user_tag()); 941 sample->set_user_tag(isolate->user_tag());
902 sample->set_thread_task(thread->task_kind()); 942 sample->set_thread_task(thread->task_kind());
903 return sample; 943 return sample;
904 } 944 }
905 945
906 946
947 static Sample* SetupNativeSample(SampleBuffer* sample_buffer, ThreadId tid) {
948 Sample* sample = sample_buffer->ReserveSample();
949 sample->Init(NULL, OS::GetCurrentMonotonicMicros(), tid);
Cutch 2017/02/08 00:28:54 You should be passing in ILLEGAL_PORT_ID and not N
bkonyi 2017/02/08 01:37:05 Done.
950 sample->set_is_native_allocation_sample(true);
951 return sample;
952 }
953
954
907 static bool CheckIsolate(Isolate* isolate) { 955 static bool CheckIsolate(Isolate* isolate) {
908 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { 956 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
909 // No isolate. 957 // No isolate.
910 return false; 958 return false;
911 } 959 }
912 return isolate != Dart::vm_isolate(); 960 return isolate != Dart::vm_isolate();
913 } 961 }
914 962
915 963
916 #if defined(TARGET_OS_WINDOWS) 964 #if defined(TARGET_OS_WINDOWS)
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 } 1031 }
984 1032
985 if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower, 1033 if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower,
986 &stack_upper)) { 1034 &stack_upper)) {
987 OS::PrintErr( 1035 OS::PrintErr(
988 "Stack dump aborted because GetAndValidateIsolateStackBounds.\n"); 1036 "Stack dump aborted because GetAndValidateIsolateStackBounds.\n");
989 return; 1037 return;
990 } 1038 }
991 1039
992 ProfilerNativeStackWalker native_stack_walker( 1040 ProfilerNativeStackWalker native_stack_walker(
993 isolate, NULL, NULL, stack_lower, stack_upper, pc, fp, sp); 1041 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, NULL, NULL,
1042 stack_lower, stack_upper, pc, fp, sp);
994 native_stack_walker.walk(); 1043 native_stack_walker.walk();
995 OS::PrintErr("-- End of DumpStackTrace\n"); 1044 OS::PrintErr("-- End of DumpStackTrace\n");
996 } 1045 }
997 1046
998 1047
999 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { 1048 void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
1000 ASSERT(thread != NULL); 1049 ASSERT(thread != NULL);
1001 OSThread* os_thread = thread->os_thread(); 1050 OSThread* os_thread = thread->os_thread();
1002 ASSERT(os_thread != NULL); 1051 ASSERT(os_thread != NULL);
1003 Isolate* isolate = thread->isolate(); 1052 Isolate* isolate = thread->isolate();
(...skipping 26 matching lines...) Expand all
1030 &stack_upper)) { 1079 &stack_upper)) {
1031 // Could not get stack boundary. 1080 // Could not get stack boundary.
1032 return; 1081 return;
1033 } 1082 }
1034 1083
1035 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); 1084 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
1036 sample->SetAllocationCid(cid); 1085 sample->SetAllocationCid(cid);
1037 1086
1038 if (FLAG_profile_vm) { 1087 if (FLAG_profile_vm) {
1039 ProfilerNativeStackWalker native_stack_walker( 1088 ProfilerNativeStackWalker native_stack_walker(
1040 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); 1089 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample,
1090 sample_buffer, stack_lower, stack_upper, pc, fp, sp);
1041 native_stack_walker.walk(); 1091 native_stack_walker.walk();
1042 } else if (exited_dart_code) { 1092 } else if (exited_dart_code) {
1043 ProfilerDartStackWalker dart_exit_stack_walker( 1093 ProfilerDartStackWalker dart_exit_stack_walker(
1044 thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp, 1094 thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp,
1045 exited_dart_code, true); 1095 exited_dart_code, true);
1046 dart_exit_stack_walker.walk(); 1096 dart_exit_stack_walker.walk();
1047 } else { 1097 } else {
1048 // Fall back. 1098 // Fall back.
1049 uintptr_t pc = GetProgramCounter(); 1099 uintptr_t pc = GetProgramCounter();
1050 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); 1100 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
1051 sample->SetAllocationCid(cid); 1101 sample->SetAllocationCid(cid);
1052 sample->SetAt(0, pc); 1102 sample->SetAt(0, pc);
1053 } 1103 }
1054 } 1104 }
1055 1105
1056 1106
1107 Sample* Profiler::NativeSampleAllocation() {
1108 SampleBuffer* sample_buffer = Profiler::sample_buffer();
1109 if (sample_buffer == NULL) {
1110 return NULL;
1111 }
1112
1113 uintptr_t sp = Thread::GetCurrentStackPointer();
1114 uintptr_t fp = 0;
1115 uintptr_t pc = GetProgramCounter();
1116
1117 COPY_FP_REGISTER(fp);
1118
1119 uword stack_lower = 0;
1120 uword stack_upper = 0;
1121 if (!InitialRegisterCheck(pc, fp, sp)) {
1122 return NULL;
1123 }
1124
1125 OSThread* os_thread = OSThread::Current();
1126 if (os_thread->stack_base() == 0) {
1127 stack_lower = sp;
1128 stack_upper = ~static_cast<uintptr_t>(0x0);
1129 } else {
1130 if (!GetAndValidateThreadStackBounds(os_thread, fp, sp, &stack_lower,
1131 &stack_upper)) {
1132 // Could not get stack boundary.
1133 return NULL;
1134 }
1135 }
1136 Sample* sample = SetupNativeSample(sample_buffer, os_thread->trace_id());
1137 ProfilerNativeStackWalker native_stack_walker(ILLEGAL_PORT, sample,
1138 sample_buffer, stack_lower,
1139 stack_upper, pc, fp, sp);
1140 native_stack_walker.walk();
1141 return sample;
1142 }
1143
1144
1057 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) { 1145 void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) {
1058 ASSERT(thread != NULL); 1146 ASSERT(thread != NULL);
1059 OSThread* os_thread = thread->os_thread(); 1147 OSThread* os_thread = thread->os_thread();
1060 ASSERT(os_thread != NULL); 1148 ASSERT(os_thread != NULL);
1061 Isolate* isolate = thread->isolate(); 1149 Isolate* isolate = thread->isolate();
1062 1150
1063 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 1151 SampleBuffer* sample_buffer = Profiler::sample_buffer();
1064 if (sample_buffer == NULL) { 1152 if (sample_buffer == NULL) {
1065 // Profiler not initialized. 1153 // Profiler not initialized.
1066 return; 1154 return;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 // Setup sample. 1260 // Setup sample.
1173 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id()); 1261 Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
1174 // Increment counter for vm tag. 1262 // Increment counter for vm tag.
1175 VMTagCounters* counters = isolate->vm_tag_counters(); 1263 VMTagCounters* counters = isolate->vm_tag_counters();
1176 ASSERT(counters != NULL); 1264 ASSERT(counters != NULL);
1177 if (thread->IsMutatorThread()) { 1265 if (thread->IsMutatorThread()) {
1178 counters->Increment(sample->vm_tag()); 1266 counters->Increment(sample->vm_tag());
1179 } 1267 }
1180 1268
1181 ProfilerNativeStackWalker native_stack_walker( 1269 ProfilerNativeStackWalker native_stack_walker(
1182 isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp); 1270 (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, sample,
1271 sample_buffer, stack_lower, stack_upper, pc, fp, sp);
1183 const bool exited_dart_code = thread->HasExitedDartCode(); 1272 const bool exited_dart_code = thread->HasExitedDartCode();
1184 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer, 1273 ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer,
1185 stack_lower, stack_upper, pc, fp, 1274 stack_lower, stack_upper, pc, fp,
1186 sp, exited_dart_code, false); 1275 sp, exited_dart_code, false);
1187 1276
1188 // All memory access is done inside CollectSample. 1277 // All memory access is done inside CollectSample.
1189 CollectSample(isolate, exited_dart_code, in_dart_code, sample, 1278 CollectSample(isolate, exited_dart_code, in_dart_code, sample,
1190 &native_stack_walker, &dart_stack_walker, pc, fp, sp, 1279 &native_stack_walker, &dart_stack_walker, pc, fp, sp,
1191 &counters_); 1280 &counters_);
1192 } 1281 }
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
1513 1602
1514 1603
1515 ProcessedSampleBuffer::ProcessedSampleBuffer() 1604 ProcessedSampleBuffer::ProcessedSampleBuffer()
1516 : code_lookup_table_(new CodeLookupTable(Thread::Current())) { 1605 : code_lookup_table_(new CodeLookupTable(Thread::Current())) {
1517 ASSERT(code_lookup_table_ != NULL); 1606 ASSERT(code_lookup_table_ != NULL);
1518 } 1607 }
1519 1608
1520 #endif // !PRODUCT 1609 #endif // !PRODUCT
1521 1610
1522 } // namespace dart 1611 } // namespace dart
OLDNEW
« runtime/vm/profiler.h ('K') | « runtime/vm/profiler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698