30 #if V8_OS_POSIX && !V8_OS_CYGWIN
40 #include <sys/syscall.h>
44 #include <mach/mach.h>
47 #elif(!V8_OS_ANDROID || defined(__BIONIC_HAVE_UCONTEXT_T)) \
56 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
57 (defined(__arm__) || defined(__aarch64__)) && \
58 !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
59 #include <asm/sigcontext.h>
62 #elif V8_OS_WIN || V8_OS_CYGWIN
80 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
91 typedef struct sigcontext mcontext_t;
93 typedef struct ucontext {
95 struct ucontext* uc_link;
97 mcontext_t uc_mcontext;
101 #elif defined(__aarch64__)
103 typedef struct sigcontext mcontext_t;
105 typedef struct ucontext {
107 struct ucontext *uc_link;
109 mcontext_t uc_mcontext;
113 #elif defined(__mips__)
136 typedef struct ucontext {
138 struct ucontext* uc_link;
140 mcontext_t uc_mcontext;
144 #elif defined(__i386__)
153 typedef uint32_t kernel_sigset_t[2];
154 typedef struct ucontext {
156 struct ucontext* uc_link;
158 mcontext_t uc_mcontext;
161 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
163 #elif defined(__x86_64__)
168 uint64_t __reserved1[8];
171 typedef struct ucontext {
173 struct ucontext *uc_link;
175 mcontext_t uc_mcontext;
178 enum { REG_RBP = 10, REG_RSP = 15, REG_RIP = 16 };
181 #endif // V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
189 class PlatformDataCommon :
public Malloced {
195 ~PlatformDataCommon() {}
203 #if defined(USE_SIGNALS)
205 class Sampler::PlatformData :
public PlatformDataCommon {
207 PlatformData() : vm_tid_(pthread_self()) {}
208 pthread_t vm_tid()
const {
return vm_tid_; }
214 #elif V8_OS_WIN || V8_OS_CYGWIN
220 class Sampler::PlatformData :
public PlatformDataCommon {
228 : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
229 THREAD_SUSPEND_RESUME |
230 THREAD_QUERY_INFORMATION,
232 GetCurrentThreadId())) {}
235 if (profiled_thread_ !=
NULL) {
236 CloseHandle(profiled_thread_);
237 profiled_thread_ =
NULL;
241 HANDLE profiled_thread() {
return profiled_thread_; }
249 #if defined(USE_SIMULATOR)
250 class SimulatorHelper {
252 inline bool Init(Sampler* sampler, Isolate* isolate) {
253 simulator_ = isolate->thread_local_top()->simulator_;
255 return simulator_ !=
NULL;
258 inline void FillRegisters(RegisterState* state) {
259 #if V8_TARGET_ARCH_ARM
260 state->pc =
reinterpret_cast<Address>(simulator_->get_pc());
261 state->sp =
reinterpret_cast<Address>(simulator_->get_register(
263 state->fp =
reinterpret_cast<Address>(simulator_->get_register(
265 #elif V8_TARGET_ARCH_ARM64
266 if (simulator_->sp() == 0 || simulator_->fp() == 0) {
273 state->pc =
reinterpret_cast<Address>(simulator_->pc());
274 state->sp =
reinterpret_cast<Address>(simulator_->sp());
275 state->fp =
reinterpret_cast<Address>(simulator_->fp());
276 #elif V8_TARGET_ARCH_MIPS
277 state->pc =
reinterpret_cast<Address>(simulator_->get_pc());
278 state->sp =
reinterpret_cast<Address>(simulator_->get_register(
280 state->fp =
reinterpret_cast<Address>(simulator_->get_register(
286 Simulator* simulator_;
288 #endif // USE_SIMULATOR
291 #if defined(USE_SIGNALS)
293 class SignalHandler :
public AllStatic {
295 static void SetUp() {
if (!mutex_) mutex_ =
new Mutex(); }
296 static void TearDown() {
delete mutex_; }
298 static void IncreaseSamplerCount() {
299 LockGuard<Mutex> lock_guard(mutex_);
300 if (++client_count_ == 1) Install();
303 static void DecreaseSamplerCount() {
304 LockGuard<Mutex> lock_guard(mutex_);
305 if (--client_count_ == 0) Restore();
308 static bool Installed() {
309 return signal_handler_installed_;
313 static void Install() {
315 sa.sa_sigaction = &HandleProfilerSignal;
316 sigemptyset(&sa.sa_mask);
318 sa.sa_flags = SA_SIGINFO;
320 sa.sa_flags = SA_RESTART | SA_SIGINFO;
322 signal_handler_installed_ =
323 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
326 static void Restore() {
327 if (signal_handler_installed_) {
328 sigaction(SIGPROF, &old_signal_handler_, 0);
329 signal_handler_installed_ =
false;
333 static void HandleProfilerSignal(
int signal, siginfo_t*
info,
void* context);
335 static Mutex* mutex_;
336 static int client_count_;
337 static bool signal_handler_installed_;
338 static struct sigaction old_signal_handler_;
342 Mutex* SignalHandler::mutex_ =
NULL;
343 int SignalHandler::client_count_ = 0;
344 struct sigaction SignalHandler::old_signal_handler_;
345 bool SignalHandler::signal_handler_installed_ =
false;
348 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
356 if (signal != SIGPROF)
return;
357 Isolate* isolate = Isolate::UncheckedCurrent();
358 if (isolate ==
NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
363 !isolate->thread_manager()->IsLockedByCurrentThread()) {
367 Sampler* sampler = isolate->logger()->sampler();
368 if (sampler ==
NULL)
return;
372 #if defined(USE_SIMULATOR)
373 SimulatorHelper helper;
374 if (!helper.Init(sampler, isolate))
return;
375 helper.FillRegisters(&state);
380 if (state.sp == 0 || state.fp == 0)
return;
383 ucontext_t* ucontext =
reinterpret_cast<ucontext_t*
>(context);
385 mcontext_t& mcontext = ucontext->uc_mcontext;
388 #if V8_HOST_ARCH_IA32
389 state.pc =
reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
390 state.sp =
reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
391 state.fp =
reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
392 #elif V8_HOST_ARCH_X64
393 state.pc =
reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
394 state.sp =
reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
395 state.fp =
reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
396 #elif V8_HOST_ARCH_ARM
397 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \
398 (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
401 state.pc =
reinterpret_cast<Address>(mcontext.gregs[R15]);
402 state.sp =
reinterpret_cast<Address>(mcontext.gregs[R13]);
403 state.fp =
reinterpret_cast<Address>(mcontext.gregs[R11]);
405 state.pc =
reinterpret_cast<Address>(mcontext.arm_pc);
406 state.sp =
reinterpret_cast<Address>(mcontext.arm_sp);
407 state.fp =
reinterpret_cast<Address>(mcontext.arm_fp);
408 #endif // defined(__GLIBC__) && !defined(__UCLIBC__) &&
410 #elif V8_HOST_ARCH_ARM64
411 state.pc =
reinterpret_cast<Address>(mcontext.pc);
412 state.sp =
reinterpret_cast<Address>(mcontext.sp);
414 state.fp =
reinterpret_cast<Address>(mcontext.regs[29]);
415 #elif V8_HOST_ARCH_MIPS
416 state.pc =
reinterpret_cast<Address>(mcontext.pc);
417 state.sp =
reinterpret_cast<Address>(mcontext.gregs[29]);
418 state.fp =
reinterpret_cast<Address>(mcontext.gregs[30]);
419 #endif // V8_HOST_ARCH_*
423 state.pc =
reinterpret_cast<Address>(mcontext->__ss.__rip);
424 state.sp =
reinterpret_cast<Address>(mcontext->__ss.__rsp);
425 state.fp =
reinterpret_cast<Address>(mcontext->__ss.__rbp);
426 #else // !__DARWIN_UNIX03
427 state.pc =
reinterpret_cast<Address>(mcontext->ss.rip);
428 state.sp =
reinterpret_cast<Address>(mcontext->ss.rsp);
429 state.fp =
reinterpret_cast<Address>(mcontext->ss.rbp);
430 #endif // __DARWIN_UNIX03
431 #elif V8_HOST_ARCH_IA32
433 state.pc =
reinterpret_cast<Address>(mcontext->__ss.__eip);
434 state.sp =
reinterpret_cast<Address>(mcontext->__ss.__esp);
435 state.fp =
reinterpret_cast<Address>(mcontext->__ss.__ebp);
436 #else // !__DARWIN_UNIX03
437 state.pc =
reinterpret_cast<Address>(mcontext->ss.eip);
438 state.sp =
reinterpret_cast<Address>(mcontext->ss.esp);
439 state.fp =
reinterpret_cast<Address>(mcontext->ss.ebp);
440 #endif // __DARWIN_UNIX03
441 #endif // V8_HOST_ARCH_IA32
443 #if V8_HOST_ARCH_IA32
444 state.pc =
reinterpret_cast<Address>(mcontext.mc_eip);
445 state.sp =
reinterpret_cast<Address>(mcontext.mc_esp);
446 state.fp =
reinterpret_cast<Address>(mcontext.mc_ebp);
447 #elif V8_HOST_ARCH_X64
448 state.pc =
reinterpret_cast<Address>(mcontext.mc_rip);
449 state.sp =
reinterpret_cast<Address>(mcontext.mc_rsp);
450 state.fp =
reinterpret_cast<Address>(mcontext.mc_rbp);
451 #elif V8_HOST_ARCH_ARM
452 state.pc =
reinterpret_cast<Address>(mcontext.mc_r15);
453 state.sp =
reinterpret_cast<Address>(mcontext.mc_r13);
454 state.fp =
reinterpret_cast<Address>(mcontext.mc_r11);
455 #endif // V8_HOST_ARCH_*
457 #if V8_HOST_ARCH_IA32
458 state.pc =
reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]);
459 state.sp =
reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]);
460 state.fp =
reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]);
461 #elif V8_HOST_ARCH_X64
462 state.pc =
reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]);
463 state.sp =
reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]);
464 state.fp =
reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]);
465 #endif // V8_HOST_ARCH_*
467 #if V8_HOST_ARCH_IA32
468 state.pc =
reinterpret_cast<Address>(ucontext->sc_eip);
469 state.sp =
reinterpret_cast<Address>(ucontext->sc_esp);
470 state.fp =
reinterpret_cast<Address>(ucontext->sc_ebp);
471 #elif V8_HOST_ARCH_X64
472 state.pc =
reinterpret_cast<Address>(ucontext->sc_rip);
473 state.sp =
reinterpret_cast<Address>(ucontext->sc_rsp);
474 state.fp =
reinterpret_cast<Address>(ucontext->sc_rbp);
475 #endif // V8_HOST_ARCH_*
477 state.pc =
reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
478 state.sp =
reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
479 state.fp =
reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
481 #if V8_HOST_ARCH_IA32
482 state.pc =
reinterpret_cast<Address>(mcontext.cpu.eip);
483 state.sp =
reinterpret_cast<Address>(mcontext.cpu.esp);
484 state.fp =
reinterpret_cast<Address>(mcontext.cpu.ebp);
485 #elif V8_HOST_ARCH_ARM
486 state.pc =
reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]);
487 state.sp =
reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]);
488 state.fp =
reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]);
489 #endif // V8_HOST_ARCH_*
491 #endif // USE_SIMULATOR
492 sampler->SampleStack(state);
505 interval_(interval) {}
507 static void SetUp() {
if (!mutex_) mutex_ =
new Mutex(); }
511 bool need_to_start =
false;
512 LockGuard<Mutex> lock_guard(mutex_);
513 if (instance_ ==
NULL) {
517 need_to_start =
true;
521 ASSERT(!instance_->active_samplers_.Contains(sampler));
523 instance_->active_samplers_.Add(sampler);
531 LockGuard<Mutex> lock_guard(mutex_);
534 bool removed = instance_->active_samplers_.RemoveElement(sampler);
540 if (instance_->active_samplers_.is_empty()) {
541 instance_to_remove = instance_;
546 if (!instance_to_remove)
return;
547 instance_to_remove->
Join();
548 delete instance_to_remove;
555 LockGuard<Mutex> lock_guard(mutex_);
556 if (active_samplers_.is_empty())
break;
559 for (
int i = 0; i < active_samplers_.length(); ++i) {
560 Sampler* sampler = active_samplers_.at(i);
572 static Mutex* mutex_;
582 Mutex* SamplerThread::mutex_ =
NULL;
583 SamplerThread* SamplerThread::instance_ =
NULL;
593 state = isolate->current_vm_state();
596 if (state ==
GC)
return;
599 if (js_entry_sp == 0) {
604 ExternalCallbackScope* scope = isolate->external_callback_scope();
609 if (scope && scope->scope_address() < handler) {
631 #if defined(USE_SIGNALS)
632 SignalHandler::SetUp();
640 #if defined(USE_SIGNALS)
641 SignalHandler::TearDown();
650 has_processing_thread_(
false),
652 is_counting_samples_(
false),
653 js_and_external_sample_count_(0) {
654 data_ =
new PlatformData;
680 #if defined(USE_SIGNALS)
681 SignalHandler::IncreaseSamplerCount();
687 #if defined(USE_SIGNALS)
688 SignalHandler::DecreaseSamplerCount();
697 if (sample ==
NULL) sample = &sample_obj;
698 sample->
Init(isolate_, state);
699 if (is_counting_samples_) {
701 ++js_and_external_sample_count_;
705 if (sample != &sample_obj) {
711 #if defined(USE_SIGNALS)
714 if (!SignalHandler::Installed())
return;
718 #elif V8_OS_WIN || V8_OS_CYGWIN
722 if (profiled_thread ==
NULL)
return;
724 #if defined(USE_SIMULATOR)
725 SimulatorHelper helper;
726 if (!helper.Init(
this, isolate()))
return;
729 const DWORD kSuspendFailed =
static_cast<DWORD>(-1);
730 if (SuspendThread(profiled_thread) == kSuspendFailed)
return;
734 memset(&context, 0,
sizeof(context));
735 context.ContextFlags = CONTEXT_FULL;
736 if (GetThreadContext(profiled_thread, &context) != 0) {
738 #if defined(USE_SIMULATOR)
739 helper.FillRegisters(&state);
742 state.pc =
reinterpret_cast<Address>(context.Rip);
743 state.sp =
reinterpret_cast<Address>(context.Rsp);
744 state.fp =
reinterpret_cast<Address>(context.Rbp);
746 state.pc =
reinterpret_cast<Address>(context.Eip);
747 state.sp =
reinterpret_cast<Address>(context.Esp);
748 state.fp =
reinterpret_cast<Address>(context.Ebp);
750 #endif // USE_SIMULATOR
753 ResumeThread(profiled_thread);
756 #endif // USE_SIGNALS
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
static void RemoveActiveSampler(Sampler *sampler)
static const int kSamplerThreadStackSize
StackFrame::Type top_frame_type() const
static const int kMaxFramesCount
SamplerThread(int interval)
Address external_callback
void DecreaseProfilingDepth()
static Address handler(ThreadLocalTop *thread)
static void AddActiveSampler(Sampler *sampler)
#define ASSERT(condition)
typedef HANDLE(__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))(DWORD dwFlags
bool has_external_callback
typedef DWORD(__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID)
void IncreaseProfilingDepth()
static Address & Address_at(Address addr)
StackFrame::Type top_frame_type
Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr, Atomic32 increment)
Address stack[kMaxFramesCount]
static void Sleep(const int milliseconds)
void StartSynchronously()
void SampleStack(const RegisterState ®s)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
CpuProfiler * cpu_profiler() const
StackFrame * frame() const
void Init(Isolate *isolate, const RegisterState &state)
Sampler(Isolate *isolate, int interval)
virtual void Tick(TickSample *sample)=0
PlatformData * platform_data() const
ThreadId profiled_thread_id_
ThreadLocalTop * thread_local_top()
TickSample * StartTickSample()
Isolate * isolate() const