Chromium Code Reviews| Index: runtime/vm/profiler.cc |
| diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc |
| index 1515eed45563e78c82a360e9283be5a103d0b259..3ab3207d4db2c0f4c65fbf5b9c7c9f04a636ae2a 100644 |
| --- a/runtime/vm/profiler.cc |
| +++ b/runtime/vm/profiler.cc |
| @@ -9,10 +9,12 @@ |
| #include "vm/allocation.h" |
| #include "vm/atomic.h" |
| #include "vm/code_patcher.h" |
| +#include "vm/debugger.h" |
| #include "vm/instructions.h" |
| #include "vm/isolate.h" |
| #include "vm/json_stream.h" |
| #include "vm/lockers.h" |
| +#include "vm/message_handler.h" |
| #include "vm/native_symbol.h" |
| #include "vm/object.h" |
| #include "vm/os.h" |
| @@ -104,54 +106,6 @@ void Profiler::SetSamplePeriod(intptr_t period) { |
| } |
| -void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) { |
| - if (!FLAG_profile) { |
| - return; |
| - } |
| - ASSERT(isolate == Isolate::Current()); |
| - ASSERT(isolate != NULL); |
| - ASSERT(sample_buffer_ != NULL); |
| - { |
| - MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); |
| - SampleBuffer* sample_buffer = sample_buffer_; |
| - if (!shared_buffer) { |
| - sample_buffer = new SampleBuffer(); |
| - } |
| - IsolateProfilerData* profiler_data = |
| - new IsolateProfilerData(sample_buffer, !shared_buffer); |
| - ASSERT(profiler_data != NULL); |
| - isolate->set_profiler_data(profiler_data); |
| - if (FLAG_trace_profiled_isolates) { |
| - OS::Print("Profiler Setup %p %s\n", isolate, isolate->name()); |
| - } |
| - } |
| - BeginExecution(isolate); |
| -} |
| - |
| - |
| -void Profiler::ShutdownProfilingForIsolate(Isolate* isolate) { |
| - ASSERT(isolate != NULL); |
| - if (!FLAG_profile) { |
| - return; |
| - } |
| - // We do not have a current isolate. |
| - ASSERT(Isolate::Current() == NULL); |
| - { |
| - MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); |
| - IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| - if (profiler_data == NULL) { |
| - // Already freed. |
| - return; |
| - } |
| - isolate->set_profiler_data(NULL); |
| - delete profiler_data; |
| - if (FLAG_trace_profiled_isolates) { |
| - OS::Print("Profiler Shutdown %p %s\n", isolate, isolate->name()); |
| - } |
| - } |
| -} |
| - |
| - |
| void Profiler::BeginExecution(Isolate* isolate) { |
|
Ivan Posva
2015/10/28 06:45:16
Is this API even needed given that we are profilin
|
| if (isolate == NULL) { |
| return; |
| @@ -160,13 +114,8 @@ void Profiler::BeginExecution(Isolate* isolate) { |
| return; |
| } |
| ASSERT(initialized_); |
| - IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| - if (profiler_data == NULL) { |
| - return; |
| - } |
| Thread* thread = Thread::Current(); |
| thread->SetThreadInterrupter(RecordSampleInterruptCallback, thread); |
| - ThreadInterrupter::WakeUp(); |
| } |
| @@ -183,41 +132,6 @@ void Profiler::EndExecution(Isolate* isolate) { |
| } |
| -IsolateProfilerData::IsolateProfilerData(SampleBuffer* sample_buffer, |
| - bool own_sample_buffer) { |
| - ASSERT(sample_buffer != NULL); |
| - sample_buffer_ = sample_buffer; |
| - own_sample_buffer_ = own_sample_buffer; |
| - block_count_ = 0; |
| -} |
| - |
| - |
| -IsolateProfilerData::~IsolateProfilerData() { |
| - if (own_sample_buffer_) { |
| - delete sample_buffer_; |
| - sample_buffer_ = NULL; |
| - own_sample_buffer_ = false; |
| - } |
| -} |
| - |
| - |
| -void IsolateProfilerData::Block() { |
| - block_count_++; |
| -} |
| - |
| - |
| -void IsolateProfilerData::Unblock() { |
| - block_count_--; |
| - if (block_count_ < 0) { |
| - FATAL("Too many calls to Dart_IsolateUnblocked."); |
| - } |
| - if (!blocked()) { |
| - // We just unblocked this isolate, wake up the thread interrupter. |
| - ThreadInterrupter::WakeUp(); |
| - } |
| -} |
| - |
| - |
| intptr_t Sample::pcs_length_ = 0; |
| intptr_t Sample::instance_size_ = 0; |
| @@ -868,8 +782,8 @@ static bool ExitedDart(Thread* thread) { |
| // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within |
| // it. Return |false| if anything looks suspicious. |
| static bool GetAndValidateIsolateStackBounds(Thread* thread, |
| - uintptr_t sp, |
| uintptr_t fp, |
| + uintptr_t sp, |
| uword* stack_lower, |
| uword* stack_upper) { |
| ASSERT(thread != NULL); |
| @@ -921,8 +835,8 @@ static bool GetAndValidateIsolateStackBounds(Thread* thread, |
| } |
| -// Some simple sanity checking of |pc|, |sp|, and |fp|. |
| -static bool InitialRegisterCheck(uintptr_t pc, uintptr_t sp, uintptr_t fp) { |
| +// Some simple sanity checking of |pc|, |fp|, and |sp|. |
| +static bool InitialRegisterCheck(uintptr_t pc, uintptr_t fp, uintptr_t sp) { |
| if ((sp == 0) || (fp == 0) || (pc == 0)) { |
| // None of these registers should be zero. |
| return false; |
| @@ -938,18 +852,6 @@ static bool InitialRegisterCheck(uintptr_t pc, uintptr_t sp, uintptr_t fp) { |
| } |
| -// Return |isolate|'s sample buffer. |
| -static SampleBuffer* GetSampleBuffer(Isolate* isolate) { |
| - IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| - if (profiler_data == NULL) { |
| - // Profiler not initialized. |
| - return NULL; |
| - } |
| - SampleBuffer* sample_buffer = profiler_data->sample_buffer(); |
| - return sample_buffer; |
| -} |
| - |
| - |
| static Sample* SetupSample(Thread* thread, |
| SampleBuffer* sample_buffer, |
| ThreadId tid) { |
| @@ -979,8 +881,7 @@ static bool CheckIsolate(Isolate* isolate) { |
| // No isolate. |
| return false; |
| } |
| - ASSERT(isolate != Dart::vm_isolate()); |
| - return true; |
| + return isolate != Dart::vm_isolate(); |
| } |
| @@ -996,7 +897,7 @@ static uintptr_t __attribute__((noinline)) GetProgramCounter() { |
| } |
| #endif |
| -void Profiler::RecordAllocation(Thread* thread, intptr_t cid) { |
| +void Profiler::SampleAllocation(Thread* thread, intptr_t cid) { |
| ASSERT(thread != NULL); |
| Isolate* isolate = thread->isolate(); |
| if (!CheckIsolate(isolate)) { |
| @@ -1005,7 +906,7 @@ void Profiler::RecordAllocation(Thread* thread, intptr_t cid) { |
| const bool exited_dart_code = ExitedDart(thread); |
| - SampleBuffer* sample_buffer = GetSampleBuffer(isolate); |
| + SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
| if (sample_buffer == NULL) { |
| // Profiler not initialized. |
| return; |
| @@ -1021,13 +922,13 @@ void Profiler::RecordAllocation(Thread* thread, intptr_t cid) { |
| uword stack_lower = 0; |
| uword stack_upper = 0; |
| - if (!InitialRegisterCheck(pc, sp, fp)) { |
| + if (!InitialRegisterCheck(pc, fp, sp)) { |
| return; |
| } |
| if (!GetAndValidateIsolateStackBounds(thread, |
| - sp, |
| fp, |
| + sp, |
| &stack_lower, |
| &stack_upper)) { |
| // Could not get stack boundary. |
| @@ -1069,64 +970,45 @@ void Profiler::RecordAllocation(Thread* thread, intptr_t cid) { |
| } |
| -void Profiler::RecordSampleInterruptCallback( |
| - const InterruptedThreadState& state, |
| - void* data) { |
| - Thread* thread = reinterpret_cast<Thread*>(data); |
| +void Profiler::SampleMutator(Thread* thread, |
|
Ivan Posva
2015/10/28 06:45:16
Not only mutator, right?
|
| + uintptr_t pc, |
| + uintptr_t fp, |
| + uintptr_t sp) { |
| + ASSERT(thread != NULL); |
| Isolate* isolate = thread->isolate(); |
| - if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { |
| - // No isolate. |
| + if (!CheckIsolate(isolate)) { |
| return; |
| } |
| - ASSERT(isolate != Dart::vm_isolate()); |
| - SampleBuffer* sample_buffer = GetSampleBuffer(isolate); |
| - if (sample_buffer == NULL) { |
| - // Profiler not initialized. |
| + if (!isolate->IsMutatorThread(thread)) { |
| + // Not the mutator thread. |
| return; |
| } |
| - const bool exited_dart_code = ExitedDart(thread); |
| - const bool in_dart_code = ExecutingDart(thread); |
| - |
| - uintptr_t sp = 0; |
| - uintptr_t fp = state.fp; |
| - uintptr_t pc = state.pc; |
| -#if defined(USING_SIMULATOR) |
| - Simulator* simulator = NULL; |
| -#endif |
| - |
| - if (in_dart_code) { |
| - // If we're in Dart code, use the Dart stack pointer. |
| -#if defined(USING_SIMULATOR) |
| - simulator = isolate->simulator(); |
| - sp = simulator->get_register(SPREG); |
| - fp = simulator->get_register(FPREG); |
| - pc = simulator->get_pc(); |
| -#else |
| - sp = state.dsp; |
| -#endif |
| - } else { |
| - // If we're in runtime code, use the C stack pointer. |
| - sp = state.csp; |
| + if (isolate->HasDebugger()) { |
| + Debugger* debugger = isolate->debugger(); |
| + if (debugger->IsPaused()) { |
| + // Mutator is paused at breakpoint. |
| + return; |
| + } |
| } |
| - if (!InitialRegisterCheck(pc, sp, fp)) { |
| + MessageHandler* msg_handler = isolate->message_handler(); |
| + if ((msg_handler != NULL) && |
| + (msg_handler->paused_on_start() || |
| + msg_handler->paused_on_exit())) { |
| + // Isolate is paused at start / exit. |
| return; |
| } |
| - if (StubCode::InJumpToExceptionHandlerStub(pc)) { |
| - // The JumpToExceptionHandler stub manually adjusts the stack pointer, |
| - // frame pointer, and some isolate state before jumping to a catch entry. |
| - // It is not safe to walk the stack when executing this stub. |
| - return; |
| - } |
| + const bool exited_dart_code = ExitedDart(thread); |
| + const bool in_dart_code = ExecutingDart(thread); |
| uword stack_lower = 0; |
| uword stack_upper = 0; |
| if (!GetAndValidateIsolateStackBounds(thread, |
| - sp, |
| fp, |
| + sp, |
| &stack_lower, |
| &stack_upper)) { |
| // Could not get stack boundary. |
| @@ -1135,6 +1017,11 @@ void Profiler::RecordSampleInterruptCallback( |
| // At this point we have a valid stack boundary for this isolate and |
| // know that our initial stack and frame pointers are within the boundary. |
| + SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
| + if (sample_buffer == NULL) { |
| + // Profiler not initialized. |
| + return; |
| + } |
| // Setup sample. |
| Sample* sample = SetupSample(thread, |
| @@ -1181,6 +1068,49 @@ void Profiler::RecordSampleInterruptCallback( |
| } |
| +void Profiler::RecordSampleInterruptCallback( |
| + const InterruptedThreadState& state, |
| + void* data) { |
| + Thread* thread = reinterpret_cast<Thread*>(data); |
|
siva
2015/10/26 23:45:26
ASSERT this is a valid thread in the thread list?
|
| + const bool in_dart_code = ExecutingDart(thread); |
|
siva
2015/10/26 23:45:26
ExecutingDart should be in class Thread now?
thre
Cutch
2015/10/27 22:36:24
Done.
|
| + |
| + uintptr_t sp = 0; |
| + uintptr_t fp = state.fp; |
| + uintptr_t pc = state.pc; |
| +#if defined(USING_SIMULATOR) |
| + Simulator* simulator = NULL; |
| +#endif |
| + |
| + if (StubCode::InJumpToExceptionHandlerStub(pc)) { |
| + // The JumpToExceptionHandler stub manually adjusts the stack pointer, |
| + // frame pointer, and some isolate state before jumping to a catch entry. |
| + // It is not safe to walk the stack when executing this stub. |
| + return; |
| + } |
| + |
| + if (in_dart_code) { |
| + // If we're in Dart code, use the Dart stack pointer. |
| +#if defined(USING_SIMULATOR) |
| + simulator = isolate->simulator(); |
| + sp = simulator->get_register(SPREG); |
| + fp = simulator->get_register(FPREG); |
| + pc = simulator->get_pc(); |
| +#else |
| + sp = state.dsp; |
| +#endif |
| + } else { |
| + // If we're in runtime code, use the C stack pointer. |
| + sp = state.csp; |
| + } |
| + |
| + if (!InitialRegisterCheck(pc, fp, sp)) { |
| + return; |
| + } |
| + |
| + SampleMutator(thread, pc, fp, sp); |
|
siva
2015/10/26 23:45:26
So we will not be profiling the background compila
Cutch
2015/10/27 22:36:24
This is intentional and temporary.
|
| +} |
| + |
| + |
| ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer( |
| SampleFilter* filter) { |
| ASSERT(filter != NULL); |