Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 23 matching lines...) Expand all Loading... | |
| 34 #else | 34 #else |
| 35 DEFINE_FLAG(int, profile_period, 1000, | 35 DEFINE_FLAG(int, profile_period, 1000, |
| 36 "Time between profiler samples in microseconds. Minimum 50."); | 36 "Time between profiler samples in microseconds. Minimum 50."); |
| 37 #endif | 37 #endif |
| 38 DEFINE_FLAG(int, profile_depth, 8, | 38 DEFINE_FLAG(int, profile_depth, 8, |
| 39 "Maximum number stack frames walked. Minimum 1. Maximum 255."); | 39 "Maximum number stack frames walked. Minimum 1. Maximum 255."); |
| 40 #if defined(USING_SIMULATOR) | 40 #if defined(USING_SIMULATOR) |
| 41 DEFINE_FLAG(bool, profile_vm, true, | 41 DEFINE_FLAG(bool, profile_vm, true, |
| 42 "Always collect native stack traces."); | 42 "Always collect native stack traces."); |
| 43 #else | 43 #else |
| 44 DEFINE_FLAG(bool, profile_vm, false, | 44 DEFINE_FLAG(bool, profile_vm, true, |
|
koda
2015/05/12 19:28:02
Please note in the CL description that you are cha
Cutch
2015/05/13 17:59:10
Done.
| |
| 45 "Always collect native stack traces."); | 45 "Always collect native stack traces."); |
| 46 #endif | 46 #endif |
| 47 | 47 |
| 48 bool Profiler::initialized_ = false; | 48 bool Profiler::initialized_ = false; |
| 49 SampleBuffer* Profiler::sample_buffer_ = NULL; | 49 SampleBuffer* Profiler::sample_buffer_ = NULL; |
| 50 | 50 |
| 51 static intptr_t NumberOfFramesToCollect() { | 51 static intptr_t NumberOfFramesToCollect() { |
| 52 if (FLAG_profile_depth <= 0) { | 52 if (FLAG_profile_depth <= 0) { |
| 53 return 0; | 53 return 0; |
| 54 } | 54 } |
| (...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 890 if (sample->vm_tag() != VMTag::kDartTagId) { | 890 if (sample->vm_tag() != VMTag::kDartTagId) { |
| 891 // We can only trust the stack pointer if we are executing Dart code. | 891 // We can only trust the stack pointer if we are executing Dart code. |
| 892 // See http://dartbug.com/20421 for details. | 892 // See http://dartbug.com/20421 for details. |
| 893 return; | 893 return; |
| 894 } | 894 } |
| 895 uword* fp = reinterpret_cast<uword*>(sample->fp()); | 895 uword* fp = reinterpret_cast<uword*>(sample->fp()); |
| 896 uword* sp = reinterpret_cast<uword*>(sample->sp()); | 896 uword* sp = reinterpret_cast<uword*>(sample->sp()); |
| 897 | 897 |
| 898 // If FP == SP, the pc marker hasn't been pushed. | 898 // If FP == SP, the pc marker hasn't been pushed. |
| 899 if (fp > sp) { | 899 if (fp > sp) { |
| 900 #if defined(TARGET_OS_WINDOWS) | |
| 901 COMPILE_ASSERT(kPcMarkerSlotFromFp < 0); | |
| 902 // If the fp is at the beginning of a page, it may be unsafe to access | |
| 903 // the pc marker, because we are reading it from a different thread on | |
| 904 // Windows. The marker is below fp and the previous page may be a guard | |
| 905 // page. | |
| 906 const intptr_t kPageMask = VirtualMemory::PageSize() - 1; | |
| 907 if ((sample->fp() & kPageMask) == 0) { | |
| 908 return; | |
| 909 } | |
| 910 #endif | |
| 911 uword* pc_marker_ptr = fp + kPcMarkerSlotFromFp; | 900 uword* pc_marker_ptr = fp + kPcMarkerSlotFromFp; |
| 912 // MSan/ASan are unaware of frames initialized by generated code. | 901 // MSan/ASan are unaware of frames initialized by generated code. |
| 913 MSAN_UNPOISON(pc_marker_ptr, kWordSize); | 902 MSAN_UNPOISON(pc_marker_ptr, kWordSize); |
| 914 ASAN_UNPOISON(pc_marker_ptr, kWordSize); | 903 ASAN_UNPOISON(pc_marker_ptr, kWordSize); |
| 915 sample->set_pc_marker(*pc_marker_ptr); | 904 sample->set_pc_marker(*pc_marker_ptr); |
| 916 } | 905 } |
| 917 } | 906 } |
| 918 | 907 |
| 919 | 908 |
| 920 static void CopyStackBuffer(Sample* sample) { | 909 static void CopyStackBuffer(Sample* sample) { |
| 921 ASSERT(sample != NULL); | 910 ASSERT(sample != NULL); |
| 922 if (sample->vm_tag() != VMTag::kDartTagId) { | 911 if (sample->vm_tag() != VMTag::kDartTagId) { |
| 923 // We can only trust the stack pointer if we are executing Dart code. | 912 // We can only trust the stack pointer if we are executing Dart code. |
| 924 // See http://dartbug.com/20421 for details. | 913 // See http://dartbug.com/20421 for details. |
| 925 return; | 914 return; |
| 926 } | 915 } |
| 927 uword* sp = reinterpret_cast<uword*>(sample->sp()); | 916 uword* sp = reinterpret_cast<uword*>(sample->sp()); |
| 928 uword* buffer = sample->GetStackBuffer(); | 917 uword* buffer = sample->GetStackBuffer(); |
| 929 if (sp != NULL) { | 918 if (sp != NULL) { |
| 930 for (intptr_t i = 0; i < Sample::kStackBufferSizeInWords; i++) { | 919 for (intptr_t i = 0; i < Sample::kStackBufferSizeInWords; i++) { |
| 931 MSAN_UNPOISON(sp, kWordSize); | 920 MSAN_UNPOISON(sp, kWordSize); |
| 932 ASAN_UNPOISON(sp, kWordSize); | 921 ASAN_UNPOISON(sp, kWordSize); |
| 933 buffer[i] = *sp; | 922 buffer[i] = *sp; |
| 934 sp++; | 923 sp++; |
| 935 } | 924 } |
| 936 } | 925 } |
| 937 } | 926 } |
| 938 | 927 |
| 939 | 928 |
| 929 #if defined(TARGET_OS_WINDOWS) | |
| 930 // On Windows this code is synchronously executed from the thread interrupter | |
| 931 // thread. This means we can safely have a static fault_address. | |
| 932 static uword fault_address = 0; | |
| 933 static LONG GuardPageExceptionFilter(EXCEPTION_POINTERS* ep) { | |
| 934 fault_address = 0; | |
| 935 if (ep->ExceptionRecord->ExceptionCode != STATUS_GUARD_PAGE_VIOLATION) { | |
| 936 return EXCEPTION_CONTINUE_SEARCH; | |
| 937 } | |
| 938 // https://goo.gl/p5Fe10 | |
| 939 fault_address = ep->ExceptionRecord->ExceptionInformation[1]; | |
|
koda
2015/05/12 19:28:03
Since I suppose we only expect this to be caused b
Vyacheslav Egorov (Google)
2015/05/12 19:46:18
I wonder if you could just do VirtualProtect in th
Cutch
2015/05/13 17:59:10
Acknowledged. I need an exception handler to jump
Cutch
2015/05/13 17:59:10
Done.
| |
| 940 return EXCEPTION_EXECUTE_HANDLER; | |
| 941 } | |
| 942 #endif | |
| 943 | |
| 944 // All memory access done to collect the sample is performed in CollectSample. | |
| 945 static void CollectSample(Isolate* isolate, | |
| 946 bool exited_dart_code, | |
| 947 bool in_dart_code, | |
| 948 Sample* sample, | |
| 949 uword stack_lower, | |
| 950 uword stack_upper, | |
| 951 uword pc, | |
| 952 uword fp, | |
| 953 uword sp) { | |
| 954 #if defined(TARGET_OS_WINDOWS) | |
| 955 // Use structured exception handling to trap guard page access on Windows. | |
| 956 __try { | |
| 957 #endif | |
| 958 | |
| 959 CopyStackBuffer(sample); | |
| 960 CopyPCMarkerIfSafe(sample); | |
| 961 | |
| 962 if (FLAG_profile_vm) { | |
| 963 // Always walk the native stack collecting both native and Dart frames. | |
| 964 ProfilerNativeStackWalker stackWalker(sample, | |
| 965 stack_lower, | |
| 966 stack_upper, | |
| 967 pc, | |
| 968 fp, | |
| 969 sp); | |
| 970 stackWalker.walk(); | |
| 971 } else if (exited_dart_code) { | |
| 972 // We have a valid exit frame info, use the Dart stack walker. | |
| 973 ProfilerDartExitStackWalker stackWalker(isolate, sample); | |
| 974 stackWalker.walk(); | |
| 975 } else if (in_dart_code) { | |
| 976 // We are executing Dart code. We have frame pointers. | |
| 977 ProfilerDartStackWalker stackWalker(isolate, | |
| 978 sample, | |
| 979 stack_lower, | |
| 980 stack_upper, | |
| 981 pc, | |
| 982 fp, | |
| 983 sp); | |
| 984 stackWalker.walk(); | |
| 985 } else { | |
| 986 sample->set_vm_tag(VMTag::kEmbedderTagId); | |
| 987 sample->SetAt(0, pc); | |
| 988 } | |
| 989 | |
| 990 #if defined(TARGET_OS_WINDOWS) | |
| 991 // Use structured exception handling to trap guard page access. | |
| 992 } __except(GuardPageExceptionFilter(GetExceptionInformation())) { | |
| 993 // Sample collection triggered a guard page fault: | |
| 994 // 1) discard entire sample. | |
| 995 sample->set_ignore_sample(true); | |
| 996 | |
| 997 // 2) Reenable guard bit on page that triggered the fault. | |
| 998 // https://goo.gl/5mCsXW | |
| 999 DWORD newProtect = PAGE_READWRITE | PAGE_GUARD; | |
|
koda
2015/05/12 19:28:03
newProtect -> new_protect, etc.
Cutch
2015/05/13 17:59:10
Done.
| |
| 1000 DWORD oldProtect = 0; | |
| 1001 BOOL r = VirtualProtect(reinterpret_cast<void*>(fault_address), | |
|
koda
2015/05/12 19:28:02
r -> success
Cutch
2015/05/13 17:59:10
Done.
| |
| 1002 sizeof(fault_address), | |
| 1003 newProtect, | |
| 1004 &oldProtect); | |
| 1005 ASSERT(r); | |
| 1006 ASSERT(oldProtect == PAGE_READWRITE); | |
| 1007 } | |
| 1008 #endif | |
| 1009 } | |
| 1010 | |
| 1011 | |
| 940 void Profiler::RecordSampleInterruptCallback( | 1012 void Profiler::RecordSampleInterruptCallback( |
| 941 const InterruptedThreadState& state, | 1013 const InterruptedThreadState& state, |
| 942 void* data) { | 1014 void* data) { |
| 943 Isolate* isolate = reinterpret_cast<Isolate*>(data); | 1015 Isolate* isolate = reinterpret_cast<Isolate*>(data); |
| 944 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { | 1016 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { |
| 945 // No isolate. | 1017 // No isolate. |
| 946 return; | 1018 return; |
| 947 } | 1019 } |
| 948 | 1020 |
| 949 ASSERT(isolate != Dart::vm_isolate()); | 1021 ASSERT(isolate != Dart::vm_isolate()); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1068 #endif | 1140 #endif |
| 1069 // Increment counter for vm tag. | 1141 // Increment counter for vm tag. |
| 1070 VMTagCounters* counters = isolate->vm_tag_counters(); | 1142 VMTagCounters* counters = isolate->vm_tag_counters(); |
| 1071 ASSERT(counters != NULL); | 1143 ASSERT(counters != NULL); |
| 1072 counters->Increment(vm_tag); | 1144 counters->Increment(vm_tag); |
| 1073 sample->set_vm_tag(vm_tag); | 1145 sample->set_vm_tag(vm_tag); |
| 1074 sample->set_user_tag(isolate->user_tag()); | 1146 sample->set_user_tag(isolate->user_tag()); |
| 1075 sample->set_sp(sp); | 1147 sample->set_sp(sp); |
| 1076 sample->set_fp(fp); | 1148 sample->set_fp(fp); |
| 1077 sample->set_lr(lr); | 1149 sample->set_lr(lr); |
| 1078 CopyStackBuffer(sample); | |
| 1079 CopyPCMarkerIfSafe(sample); | |
| 1080 | 1150 |
| 1081 if (FLAG_profile_vm) { | 1151 // All memory access is done inside CollectSample. |
| 1082 // Always walk the native stack collecting both native and Dart frames. | 1152 CollectSample(isolate, |
| 1083 ProfilerNativeStackWalker stackWalker(sample, | 1153 exited_dart_code, |
| 1084 stack_lower, | 1154 in_dart_code, |
| 1085 stack_upper, | 1155 sample, |
| 1086 pc, | 1156 stack_lower, |
| 1087 fp, | 1157 stack_upper, |
| 1088 sp); | 1158 pc, |
| 1089 stackWalker.walk(); | 1159 fp, |
| 1090 } else if (exited_dart_code) { | 1160 sp); |
| 1091 // We have a valid exit frame info, use the Dart stack walker. | |
| 1092 ProfilerDartExitStackWalker stackWalker(isolate, sample); | |
| 1093 stackWalker.walk(); | |
| 1094 } else if (in_dart_code) { | |
| 1095 // We are executing Dart code. We have frame pointers. | |
| 1096 ProfilerDartStackWalker stackWalker(isolate, | |
| 1097 sample, | |
| 1098 stack_lower, | |
| 1099 stack_upper, | |
| 1100 pc, | |
| 1101 fp, | |
| 1102 sp); | |
| 1103 stackWalker.walk(); | |
| 1104 } else { | |
| 1105 sample->set_vm_tag(VMTag::kEmbedderTagId); | |
| 1106 sample->SetAt(0, pc); | |
| 1107 } | |
| 1108 } | 1161 } |
| 1109 | 1162 |
| 1110 } // namespace dart | 1163 } // namespace dart |
| OLD | NEW |