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

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

Issue 1131233005: Use Structured Exception Handler on Windows to gracefully handle guard page faults (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 7 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 | « no previous file | 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 23 matching lines...) Expand all
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698