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

Side by Side Diff: src/sampler.cc

Issue 596533002: Initial implementation of GetStackSample sampling profiler API. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix ARM32 build. Created 6 years, 2 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 | « src/sampler.h ('k') | src/vm-state.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/sampler.h" 5 #include "src/sampler.h"
6 6
7 #if V8_OS_POSIX && !V8_OS_CYGWIN 7 #if V8_OS_POSIX && !V8_OS_CYGWIN
8 8
9 #define USE_SIGNALS 9 #define USE_SIGNALS
10 10
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 219
220 private: 220 private:
221 HANDLE profiled_thread_; 221 HANDLE profiled_thread_;
222 }; 222 };
223 #endif 223 #endif
224 224
225 225
226 #if defined(USE_SIMULATOR) 226 #if defined(USE_SIMULATOR)
227 class SimulatorHelper { 227 class SimulatorHelper {
228 public: 228 public:
229 inline bool Init(Sampler* sampler, Isolate* isolate) { 229 inline bool Init(Isolate* isolate) {
230 simulator_ = isolate->thread_local_top()->simulator_; 230 simulator_ = isolate->thread_local_top()->simulator_;
231 // Check if there is active simulator. 231 // Check if there is active simulator.
232 return simulator_ != NULL; 232 return simulator_ != NULL;
233 } 233 }
234 234
235 inline void FillRegisters(RegisterState* state) { 235 inline void FillRegisters(v8::RegisterState* state) {
236 #if V8_TARGET_ARCH_ARM 236 #if V8_TARGET_ARCH_ARM
237 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 237 state->pc = reinterpret_cast<Address>(simulator_->get_pc());
238 state->sp = reinterpret_cast<Address>(simulator_->get_register( 238 state->sp = reinterpret_cast<Address>(simulator_->get_register(
239 Simulator::sp)); 239 Simulator::sp));
240 state->fp = reinterpret_cast<Address>(simulator_->get_register( 240 state->fp = reinterpret_cast<Address>(simulator_->get_register(
241 Simulator::r11)); 241 Simulator::r11));
242 #elif V8_TARGET_ARCH_ARM64 242 #elif V8_TARGET_ARCH_ARM64
243 if (simulator_->sp() == 0 || simulator_->fp() == 0) { 243 if (simulator_->sp() == 0 || simulator_->fp() == 0) {
244 // It possible that the simulator is interrupted while it is updating 244 // It's possible that the simulator is interrupted while it is updating
245 // the sp or fp register. ARM64 simulator does this in two steps: 245 // the sp or fp register. ARM64 simulator does this in two steps:
246 // first setting it to zero and then setting it to the new value. 246 // first setting it to zero and then setting it to a new value.
247 // Bailout if sp/fp doesn't contain the new value. 247 // Bailout if sp/fp doesn't contain the new value.
248 return; 248 return;
249 } 249 }
250 state->pc = reinterpret_cast<Address>(simulator_->pc()); 250 state->pc = reinterpret_cast<Address>(simulator_->pc());
251 state->sp = reinterpret_cast<Address>(simulator_->sp()); 251 state->sp = reinterpret_cast<Address>(simulator_->sp());
252 state->fp = reinterpret_cast<Address>(simulator_->fp()); 252 state->fp = reinterpret_cast<Address>(simulator_->fp());
253 #elif V8_TARGET_ARCH_MIPS 253 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
254 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 254 state->pc = reinterpret_cast<Address>(simulator_->get_pc());
255 state->sp = reinterpret_cast<Address>(simulator_->get_register( 255 state->sp = reinterpret_cast<Address>(simulator_->get_register(
256 Simulator::sp)); 256 Simulator::sp));
257 state->fp = reinterpret_cast<Address>(simulator_->get_register(
258 Simulator::fp));
259 #elif V8_TARGET_ARCH_MIPS64
260 state->pc = reinterpret_cast<Address>(simulator_->get_pc());
261 state->sp = reinterpret_cast<Address>(simulator_->get_register(
262 Simulator::sp));
263 state->fp = reinterpret_cast<Address>(simulator_->get_register( 257 state->fp = reinterpret_cast<Address>(simulator_->get_register(
264 Simulator::fp)); 258 Simulator::fp));
265 #endif 259 #endif
266 } 260 }
267 261
268 private: 262 private:
269 Simulator* simulator_; 263 Simulator* simulator_;
270 }; 264 };
271 #endif // USE_SIMULATOR 265 #endif // USE_SIMULATOR
272 266
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 return; 340 return;
347 } 341 }
348 if (v8::Locker::IsActive() && 342 if (v8::Locker::IsActive() &&
349 !isolate->thread_manager()->IsLockedByCurrentThread()) { 343 !isolate->thread_manager()->IsLockedByCurrentThread()) {
350 return; 344 return;
351 } 345 }
352 346
353 Sampler* sampler = isolate->logger()->sampler(); 347 Sampler* sampler = isolate->logger()->sampler();
354 if (sampler == NULL) return; 348 if (sampler == NULL) return;
355 349
356 RegisterState state; 350 v8::RegisterState state;
357 351
358 #if defined(USE_SIMULATOR) 352 #if defined(USE_SIMULATOR)
359 SimulatorHelper helper; 353 SimulatorHelper helper;
360 if (!helper.Init(sampler, isolate)) return; 354 if (!helper.Init(isolate)) return;
361 helper.FillRegisters(&state); 355 helper.FillRegisters(&state);
362 // It possible that the simulator is interrupted while it is updating 356 // It possible that the simulator is interrupted while it is updating
363 // the sp or fp register. ARM64 simulator does this in two steps: 357 // the sp or fp register. ARM64 simulator does this in two steps:
364 // first setting it to zero and then setting it to the new value. 358 // first setting it to zero and then setting it to the new value.
365 // Bailout if sp/fp doesn't contain the new value. 359 // Bailout if sp/fp doesn't contain the new value.
366 if (state.sp == 0 || state.fp == 0) return; 360 if (state.sp == 0 || state.fp == 0) return;
367 #else 361 #else
368 // Extracting the sample from the context is extremely machine dependent. 362 // Extracting the sample from the context is extremely machine dependent.
369 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 363 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
370 #if !V8_OS_OPENBSD 364 #if !V8_OS_OPENBSD
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 564
571 565
572 base::Mutex* SamplerThread::mutex_ = NULL; 566 base::Mutex* SamplerThread::mutex_ = NULL;
573 SamplerThread* SamplerThread::instance_ = NULL; 567 SamplerThread* SamplerThread::instance_ = NULL;
574 568
575 569
576 // 570 //
577 // StackTracer implementation 571 // StackTracer implementation
578 // 572 //
579 DISABLE_ASAN void TickSample::Init(Isolate* isolate, 573 DISABLE_ASAN void TickSample::Init(Isolate* isolate,
580 const RegisterState& regs) { 574 const v8::RegisterState& regs) {
581 DCHECK(isolate->IsInitialized()); 575 DCHECK(isolate->IsInitialized());
582 timestamp = base::TimeTicks::HighResolutionNow(); 576 timestamp = base::TimeTicks::HighResolutionNow();
583 pc = regs.pc; 577 pc = reinterpret_cast<Address>(regs.pc);
584 state = isolate->current_vm_state(); 578 state = isolate->current_vm_state();
585 579
586 // Avoid collecting traces while doing GC. 580 // Avoid collecting traces while doing GC.
587 if (state == GC) return; 581 if (state == GC) return;
588 582
589 Address js_entry_sp = isolate->js_entry_sp(); 583 Address js_entry_sp = isolate->js_entry_sp();
590 if (js_entry_sp == 0) { 584 if (js_entry_sp == 0) return; // Not executing JS now.
591 // Not executing JS now.
592 return;
593 }
594 585
595 ExternalCallbackScope* scope = isolate->external_callback_scope(); 586 ExternalCallbackScope* scope = isolate->external_callback_scope();
596 Address handler = Isolate::handler(isolate->thread_local_top()); 587 Address handler = Isolate::handler(isolate->thread_local_top());
597 // If there is a handler on top of the external callback scope then 588 // If there is a handler on top of the external callback scope then
598 // we have already entrered JavaScript again and the external callback 589 // we have already entrered JavaScript again and the external callback
599 // is not the top function. 590 // is not the top function.
600 if (scope && scope->scope_address() < handler) { 591 if (scope && scope->scope_address() < handler) {
601 external_callback = scope->callback(); 592 external_callback = scope->callback();
602 has_external_callback = true; 593 has_external_callback = true;
603 } else { 594 } else {
604 // Sample potential return address value for frameless invocation of 595 // Sample potential return address value for frameless invocation of
605 // stubs (we'll figure out later, if this value makes sense). 596 // stubs (we'll figure out later, if this value makes sense).
606 tos = Memory::Address_at(regs.sp); 597 tos = Memory::Address_at(reinterpret_cast<Address>(regs.sp));
607 has_external_callback = false; 598 has_external_callback = false;
608 } 599 }
609 600
610 SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp); 601 SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp),
602 reinterpret_cast<Address>(regs.sp), js_entry_sp);
611 top_frame_type = it.top_frame_type(); 603 top_frame_type = it.top_frame_type();
612 unsigned i = 0; 604
613 while (!it.done() && i < TickSample::kMaxFramesCount) { 605 SampleInfo info;
614 stack[i++] = it.frame()->pc(); 606 GetStackSample(isolate, regs, reinterpret_cast<void**>(&stack[0]),
615 it.Advance(); 607 kMaxFramesCount, &info);
616 } 608 frames_count = static_cast<unsigned>(info.frames_count);
617 frames_count = i;
618 } 609 }
619 610
620 611
612 void TickSample::GetStackSample(Isolate* isolate, const v8::RegisterState& regs,
613 void** frames, size_t frames_limit,
614 v8::SampleInfo* sample_info) {
615 DCHECK(isolate->IsInitialized());
616 sample_info->frames_count = 0;
617 sample_info->vm_state = isolate->current_vm_state();
618 if (sample_info->vm_state == GC) return;
619
620 Address js_entry_sp = isolate->js_entry_sp();
621 if (js_entry_sp == 0) return; // Not executing JS now.
622
623 SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp),
624 reinterpret_cast<Address>(regs.sp), js_entry_sp);
625 size_t i = 0;
626 while (!it.done() && i < frames_limit) {
627 frames[i++] = it.frame()->pc();
628 it.Advance();
629 }
630 sample_info->frames_count = i;
631 }
632
633
621 void Sampler::SetUp() { 634 void Sampler::SetUp() {
622 #if defined(USE_SIGNALS) 635 #if defined(USE_SIGNALS)
623 SignalHandler::SetUp(); 636 SignalHandler::SetUp();
624 #endif 637 #endif
625 SamplerThread::SetUp(); 638 SamplerThread::SetUp();
626 } 639 }
627 640
628 641
629 void Sampler::TearDown() { 642 void Sampler::TearDown() {
630 SamplerThread::TearDown(); 643 SamplerThread::TearDown();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 688
676 689
677 void Sampler::DecreaseProfilingDepth() { 690 void Sampler::DecreaseProfilingDepth() {
678 #if defined(USE_SIGNALS) 691 #if defined(USE_SIGNALS)
679 SignalHandler::DecreaseSamplerCount(); 692 SignalHandler::DecreaseSamplerCount();
680 #endif 693 #endif
681 base::NoBarrier_AtomicIncrement(&profiling_, -1); 694 base::NoBarrier_AtomicIncrement(&profiling_, -1);
682 } 695 }
683 696
684 697
685 void Sampler::SampleStack(const RegisterState& state) { 698 void Sampler::SampleStack(const v8::RegisterState& state) {
686 TickSample* sample = isolate_->cpu_profiler()->StartTickSample(); 699 TickSample* sample = isolate_->cpu_profiler()->StartTickSample();
687 TickSample sample_obj; 700 TickSample sample_obj;
688 if (sample == NULL) sample = &sample_obj; 701 if (sample == NULL) sample = &sample_obj;
689 sample->Init(isolate_, state); 702 sample->Init(isolate_, state);
690 if (is_counting_samples_) { 703 if (is_counting_samples_) {
691 if (sample->state == JS || sample->state == EXTERNAL) { 704 if (sample->state == JS || sample->state == EXTERNAL) {
692 ++js_and_external_sample_count_; 705 ++js_and_external_sample_count_;
693 } 706 }
694 } 707 }
695 Tick(sample); 708 Tick(sample);
(...skipping 11 matching lines...) Expand all
707 } 720 }
708 721
709 #elif V8_OS_WIN || V8_OS_CYGWIN 722 #elif V8_OS_WIN || V8_OS_CYGWIN
710 723
711 void Sampler::DoSample() { 724 void Sampler::DoSample() {
712 HANDLE profiled_thread = platform_data()->profiled_thread(); 725 HANDLE profiled_thread = platform_data()->profiled_thread();
713 if (profiled_thread == NULL) return; 726 if (profiled_thread == NULL) return;
714 727
715 #if defined(USE_SIMULATOR) 728 #if defined(USE_SIMULATOR)
716 SimulatorHelper helper; 729 SimulatorHelper helper;
717 if (!helper.Init(this, isolate())) return; 730 if (!helper.Init(isolate())) return;
718 #endif 731 #endif
719 732
720 const DWORD kSuspendFailed = static_cast<DWORD>(-1); 733 const DWORD kSuspendFailed = static_cast<DWORD>(-1);
721 if (SuspendThread(profiled_thread) == kSuspendFailed) return; 734 if (SuspendThread(profiled_thread) == kSuspendFailed) return;
722 735
723 // Context used for sampling the register state of the profiled thread. 736 // Context used for sampling the register state of the profiled thread.
724 CONTEXT context; 737 CONTEXT context;
725 memset(&context, 0, sizeof(context)); 738 memset(&context, 0, sizeof(context));
726 context.ContextFlags = CONTEXT_FULL; 739 context.ContextFlags = CONTEXT_FULL;
727 if (GetThreadContext(profiled_thread, &context) != 0) { 740 if (GetThreadContext(profiled_thread, &context) != 0) {
728 RegisterState state; 741 v8::RegisterState state;
729 #if defined(USE_SIMULATOR) 742 #if defined(USE_SIMULATOR)
730 helper.FillRegisters(&state); 743 helper.FillRegisters(&state);
731 #else 744 #else
732 #if V8_HOST_ARCH_X64 745 #if V8_HOST_ARCH_X64
733 state.pc = reinterpret_cast<Address>(context.Rip); 746 state.pc = reinterpret_cast<Address>(context.Rip);
734 state.sp = reinterpret_cast<Address>(context.Rsp); 747 state.sp = reinterpret_cast<Address>(context.Rsp);
735 state.fp = reinterpret_cast<Address>(context.Rbp); 748 state.fp = reinterpret_cast<Address>(context.Rbp);
736 #else 749 #else
737 state.pc = reinterpret_cast<Address>(context.Eip); 750 state.pc = reinterpret_cast<Address>(context.Eip);
738 state.sp = reinterpret_cast<Address>(context.Esp); 751 state.sp = reinterpret_cast<Address>(context.Esp);
739 state.fp = reinterpret_cast<Address>(context.Ebp); 752 state.fp = reinterpret_cast<Address>(context.Ebp);
740 #endif 753 #endif
741 #endif // USE_SIMULATOR 754 #endif // USE_SIMULATOR
742 SampleStack(state); 755 SampleStack(state);
743 } 756 }
744 ResumeThread(profiled_thread); 757 ResumeThread(profiled_thread);
745 } 758 }
746 759
747 #endif // USE_SIGNALS 760 #endif // USE_SIGNALS
748 761
749 762
750 } } // namespace v8::internal 763 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/sampler.h ('k') | src/vm-state.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698