Chromium Code Reviews| Index: runtime/vm/profiler.cc |
| =================================================================== |
| --- runtime/vm/profiler.cc (revision 45709) |
| +++ runtime/vm/profiler.cc (working copy) |
| @@ -41,7 +41,7 @@ |
| DEFINE_FLAG(bool, profile_vm, true, |
| "Always collect native stack traces."); |
| #else |
| -DEFINE_FLAG(bool, profile_vm, false, |
| +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.
|
| "Always collect native stack traces."); |
| #endif |
| @@ -897,17 +897,6 @@ |
| // If FP == SP, the pc marker hasn't been pushed. |
| if (fp > sp) { |
| -#if defined(TARGET_OS_WINDOWS) |
| - COMPILE_ASSERT(kPcMarkerSlotFromFp < 0); |
| - // If the fp is at the beginning of a page, it may be unsafe to access |
| - // the pc marker, because we are reading it from a different thread on |
| - // Windows. The marker is below fp and the previous page may be a guard |
| - // page. |
| - const intptr_t kPageMask = VirtualMemory::PageSize() - 1; |
| - if ((sample->fp() & kPageMask) == 0) { |
| - return; |
| - } |
| -#endif |
| uword* pc_marker_ptr = fp + kPcMarkerSlotFromFp; |
| // MSan/ASan are unaware of frames initialized by generated code. |
| MSAN_UNPOISON(pc_marker_ptr, kWordSize); |
| @@ -937,6 +926,89 @@ |
| } |
| +#if defined(TARGET_OS_WINDOWS) |
| +// On Windows this code is synchronously executed from the thread interrupter |
| +// thread. This means we can safely have a static fault_address. |
| +static uword fault_address = 0; |
| +static LONG GuardPageExceptionFilter(EXCEPTION_POINTERS* ep) { |
| + fault_address = 0; |
| + if (ep->ExceptionRecord->ExceptionCode != STATUS_GUARD_PAGE_VIOLATION) { |
| + return EXCEPTION_CONTINUE_SEARCH; |
| + } |
| + // https://goo.gl/p5Fe10 |
| + 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.
|
| + return EXCEPTION_EXECUTE_HANDLER; |
| +} |
| +#endif |
| + |
| +// All memory access done to collect the sample is performed in CollectSample. |
| +static void CollectSample(Isolate* isolate, |
| + bool exited_dart_code, |
| + bool in_dart_code, |
| + Sample* sample, |
| + uword stack_lower, |
| + uword stack_upper, |
| + uword pc, |
| + uword fp, |
| + uword sp) { |
| +#if defined(TARGET_OS_WINDOWS) |
| + // Use structured exception handling to trap guard page access on Windows. |
| + __try { |
| +#endif |
| + |
| + CopyStackBuffer(sample); |
| + CopyPCMarkerIfSafe(sample); |
| + |
| + if (FLAG_profile_vm) { |
| + // Always walk the native stack collecting both native and Dart frames. |
| + ProfilerNativeStackWalker stackWalker(sample, |
| + stack_lower, |
| + stack_upper, |
| + pc, |
| + fp, |
| + sp); |
| + stackWalker.walk(); |
| + } else if (exited_dart_code) { |
| + // We have a valid exit frame info, use the Dart stack walker. |
| + ProfilerDartExitStackWalker stackWalker(isolate, sample); |
| + stackWalker.walk(); |
| + } else if (in_dart_code) { |
| + // We are executing Dart code. We have frame pointers. |
| + ProfilerDartStackWalker stackWalker(isolate, |
| + sample, |
| + stack_lower, |
| + stack_upper, |
| + pc, |
| + fp, |
| + sp); |
| + stackWalker.walk(); |
| + } else { |
| + sample->set_vm_tag(VMTag::kEmbedderTagId); |
| + sample->SetAt(0, pc); |
| + } |
| + |
| +#if defined(TARGET_OS_WINDOWS) |
| + // Use structured exception handling to trap guard page access. |
| + } __except(GuardPageExceptionFilter(GetExceptionInformation())) { |
| + // Sample collection triggered a guard page fault: |
| + // 1) discard entire sample. |
| + sample->set_ignore_sample(true); |
| + |
| + // 2) Reenable guard bit on page that triggered the fault. |
| + // https://goo.gl/5mCsXW |
| + 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.
|
| + DWORD oldProtect = 0; |
| + 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.
|
| + sizeof(fault_address), |
| + newProtect, |
| + &oldProtect); |
| + ASSERT(r); |
| + ASSERT(oldProtect == PAGE_READWRITE); |
| + } |
| +#endif |
| +} |
| + |
| + |
| void Profiler::RecordSampleInterruptCallback( |
| const InterruptedThreadState& state, |
| void* data) { |
| @@ -1075,36 +1147,17 @@ |
| sample->set_sp(sp); |
| sample->set_fp(fp); |
| sample->set_lr(lr); |
| - CopyStackBuffer(sample); |
| - CopyPCMarkerIfSafe(sample); |
| - if (FLAG_profile_vm) { |
| - // Always walk the native stack collecting both native and Dart frames. |
| - ProfilerNativeStackWalker stackWalker(sample, |
| - stack_lower, |
| - stack_upper, |
| - pc, |
| - fp, |
| - sp); |
| - stackWalker.walk(); |
| - } else if (exited_dart_code) { |
| - // We have a valid exit frame info, use the Dart stack walker. |
| - ProfilerDartExitStackWalker stackWalker(isolate, sample); |
| - stackWalker.walk(); |
| - } else if (in_dart_code) { |
| - // We are executing Dart code. We have frame pointers. |
| - ProfilerDartStackWalker stackWalker(isolate, |
| - sample, |
| - stack_lower, |
| - stack_upper, |
| - pc, |
| - fp, |
| - sp); |
| - stackWalker.walk(); |
| - } else { |
| - sample->set_vm_tag(VMTag::kEmbedderTagId); |
| - sample->SetAt(0, pc); |
| - } |
| + // All memory access is done inside CollectSample. |
| + CollectSample(isolate, |
| + exited_dart_code, |
| + in_dart_code, |
| + sample, |
| + stack_lower, |
| + stack_upper, |
| + pc, |
| + fp, |
| + sp); |
| } |
| } // namespace dart |