7 #if V8_OS_POSIX && !V8_OS_CYGWIN
16 #if !V8_OS_QNX && !V8_OS_NACL
17 #include <sys/syscall.h>
21 #include <mach/mach.h>
24 #elif(!V8_OS_ANDROID || defined(__BIONIC_HAVE_UCONTEXT_T)) && \
25 !V8_OS_OPENBSD && !V8_OS_NACL
33 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
34 (defined(__arm__) || defined(__aarch64__)) && \
35 !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
36 #include <asm/sigcontext.h>
39 #elif V8_OS_WIN || V8_OS_CYGWIN
57 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
68 typedef struct sigcontext mcontext_t;
70 typedef struct ucontext {
72 struct ucontext* uc_link;
74 mcontext_t uc_mcontext;
78 #elif defined(__aarch64__)
80 typedef struct sigcontext mcontext_t;
82 typedef struct ucontext {
84 struct ucontext *uc_link;
86 mcontext_t uc_mcontext;
90 #elif defined(__mips__)
113 typedef struct ucontext {
115 struct ucontext* uc_link;
117 mcontext_t uc_mcontext;
121 #elif defined(__i386__)
130 typedef uint32_t kernel_sigset_t[2];
131 typedef struct ucontext {
133 struct ucontext* uc_link;
135 mcontext_t uc_mcontext;
138 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
140 #elif defined(__x86_64__)
145 uint64_t __reserved1[8];
148 typedef struct ucontext {
150 struct ucontext *uc_link;
152 mcontext_t uc_mcontext;
155 enum { REG_RBP = 10, REG_RSP = 15, REG_RIP = 16 };
180 #if defined(USE_SIGNALS)
182 class Sampler::PlatformData :
public PlatformDataCommon {
184 PlatformData() : vm_tid_(pthread_self()) {}
185 pthread_t vm_tid()
const {
return vm_tid_; }
191 #elif V8_OS_WIN || V8_OS_CYGWIN
197 class Sampler::PlatformData :
public PlatformDataCommon {
205 : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
206 THREAD_SUSPEND_RESUME |
207 THREAD_QUERY_INFORMATION,
209 GetCurrentThreadId())) {}
212 if (profiled_thread_ !=
NULL) {
213 CloseHandle(profiled_thread_);
214 profiled_thread_ =
NULL;
218 HANDLE profiled_thread() {
return profiled_thread_; }
226 #if defined(USE_SIMULATOR)
227 class SimulatorHelper {
229 inline bool Init(Sampler* sampler, Isolate* isolate) {
230 simulator_ = isolate->thread_local_top()->simulator_;
232 return simulator_ !=
NULL;
235 inline void FillRegisters(RegisterState* state) {
236 #if V8_TARGET_ARCH_ARM
237 state->pc =
reinterpret_cast<Address>(simulator_->get_pc());
238 state->sp =
reinterpret_cast<Address>(simulator_->get_register(
240 state->fp =
reinterpret_cast<Address>(simulator_->get_register(
242 #elif V8_TARGET_ARCH_ARM64
243 if (simulator_->sp() == 0 || simulator_->fp() == 0) {
250 state->pc =
reinterpret_cast<Address>(simulator_->pc());
251 state->sp =
reinterpret_cast<Address>(simulator_->sp());
252 state->fp =
reinterpret_cast<Address>(simulator_->fp());
253 #elif V8_TARGET_ARCH_MIPS
254 state->pc =
reinterpret_cast<Address>(simulator_->get_pc());
255 state->sp =
reinterpret_cast<Address>(simulator_->get_register(
257 state->fp =
reinterpret_cast<Address>(simulator_->get_register(
259 #elif V8_TARGET_ARCH_MIPS64
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(
269 Simulator* simulator_;
274 #if defined(USE_SIGNALS)
276 class SignalHandler :
public AllStatic {
278 static void SetUp() {
if (!mutex_) mutex_ =
new base::Mutex(); }
279 static void TearDown() {
delete mutex_; mutex_ =
NULL; }
281 static void IncreaseSamplerCount() {
282 base::LockGuard<base::Mutex> lock_guard(mutex_);
283 if (++client_count_ == 1) Install();
286 static void DecreaseSamplerCount() {
287 base::LockGuard<base::Mutex> lock_guard(mutex_);
288 if (--client_count_ == 0) Restore();
291 static bool Installed() {
292 return signal_handler_installed_;
296 static void Install() {
299 sa.sa_sigaction = &HandleProfilerSignal;
300 sigemptyset(&sa.sa_mask);
302 sa.sa_flags = SA_SIGINFO;
304 sa.sa_flags = SA_RESTART | SA_SIGINFO;
306 signal_handler_installed_ =
307 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
311 static void Restore() {
313 if (signal_handler_installed_) {
314 sigaction(SIGPROF, &old_signal_handler_, 0);
315 signal_handler_installed_ =
false;
321 static void HandleProfilerSignal(
int signal, siginfo_t* info,
void* context);
324 static base::Mutex* mutex_;
325 static int client_count_;
326 static bool signal_handler_installed_;
327 static struct sigaction old_signal_handler_;
331 base::Mutex* SignalHandler::mutex_ =
NULL;
332 int SignalHandler::client_count_ = 0;
333 struct sigaction SignalHandler::old_signal_handler_;
334 bool SignalHandler::signal_handler_installed_ =
false;
339 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
342 if (signal != SIGPROF)
return;
343 Isolate* isolate = Isolate::UnsafeCurrent();
344 if (isolate ==
NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
349 !isolate->thread_manager()->IsLockedByCurrentThread()) {
353 Sampler* sampler = isolate->logger()->sampler();
354 if (sampler ==
NULL)
return;
358 #if defined(USE_SIMULATOR)
359 SimulatorHelper helper;
360 if (!helper.Init(sampler, isolate))
return;
361 helper.FillRegisters(&state);
366 if (state.sp == 0 || state.fp == 0)
return;
369 ucontext_t* ucontext =
reinterpret_cast<ucontext_t*
>(context);
371 mcontext_t& mcontext = ucontext->uc_mcontext;
374 #if V8_HOST_ARCH_IA32
375 state.pc =
reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
376 state.sp =
reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
377 state.fp =
reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
378 #elif V8_HOST_ARCH_X64
379 state.pc =
reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
380 state.sp =
reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
381 state.fp =
reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
382 #elif V8_HOST_ARCH_ARM
383 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \
384 (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
387 state.pc =
reinterpret_cast<Address>(mcontext.gregs[R15]);
388 state.sp =
reinterpret_cast<Address>(mcontext.gregs[R13]);
389 state.fp =
reinterpret_cast<Address>(mcontext.gregs[R11]);
391 state.pc =
reinterpret_cast<Address>(mcontext.arm_pc);
392 state.sp =
reinterpret_cast<Address>(mcontext.arm_sp);
393 state.fp =
reinterpret_cast<Address>(mcontext.arm_fp);
396 #elif V8_HOST_ARCH_ARM64
397 state.pc =
reinterpret_cast<Address>(mcontext.pc);
398 state.sp =
reinterpret_cast<Address>(mcontext.sp);
400 state.fp =
reinterpret_cast<Address>(mcontext.regs[29]);
401 #elif V8_HOST_ARCH_MIPS
402 state.pc =
reinterpret_cast<Address>(mcontext.pc);
403 state.sp =
reinterpret_cast<Address>(mcontext.gregs[29]);
404 state.fp =
reinterpret_cast<Address>(mcontext.gregs[30]);
405 #elif V8_HOST_ARCH_MIPS64
406 state.pc =
reinterpret_cast<Address>(mcontext.pc);
407 state.sp =
reinterpret_cast<Address>(mcontext.gregs[29]);
408 state.fp =
reinterpret_cast<Address>(mcontext.gregs[30]);
413 state.pc =
reinterpret_cast<Address>(mcontext->__ss.__rip);
414 state.sp =
reinterpret_cast<Address>(mcontext->__ss.__rsp);
415 state.fp =
reinterpret_cast<Address>(mcontext->__ss.__rbp);
417 state.pc =
reinterpret_cast<Address>(mcontext->ss.rip);
418 state.sp =
reinterpret_cast<Address>(mcontext->ss.rsp);
419 state.fp =
reinterpret_cast<Address>(mcontext->ss.rbp);
421 #elif V8_HOST_ARCH_IA32
423 state.pc =
reinterpret_cast<Address>(mcontext->__ss.__eip);
424 state.sp =
reinterpret_cast<Address>(mcontext->__ss.__esp);
425 state.fp =
reinterpret_cast<Address>(mcontext->__ss.__ebp);
427 state.pc =
reinterpret_cast<Address>(mcontext->ss.eip);
428 state.sp =
reinterpret_cast<Address>(mcontext->ss.esp);
429 state.fp =
reinterpret_cast<Address>(mcontext->ss.ebp);
433 #if V8_HOST_ARCH_IA32
434 state.pc =
reinterpret_cast<Address>(mcontext.mc_eip);
435 state.sp =
reinterpret_cast<Address>(mcontext.mc_esp);
436 state.fp =
reinterpret_cast<Address>(mcontext.mc_ebp);
437 #elif V8_HOST_ARCH_X64
438 state.pc =
reinterpret_cast<Address>(mcontext.mc_rip);
439 state.sp =
reinterpret_cast<Address>(mcontext.mc_rsp);
440 state.fp =
reinterpret_cast<Address>(mcontext.mc_rbp);
441 #elif V8_HOST_ARCH_ARM
442 state.pc =
reinterpret_cast<Address>(mcontext.mc_r15);
443 state.sp =
reinterpret_cast<Address>(mcontext.mc_r13);
444 state.fp =
reinterpret_cast<Address>(mcontext.mc_r11);
447 #if V8_HOST_ARCH_IA32
448 state.pc =
reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]);
449 state.sp =
reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]);
450 state.fp =
reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]);
451 #elif V8_HOST_ARCH_X64
452 state.pc =
reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]);
453 state.sp =
reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]);
454 state.fp =
reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]);
457 #if V8_HOST_ARCH_IA32
458 state.pc =
reinterpret_cast<Address>(ucontext->sc_eip);
459 state.sp =
reinterpret_cast<Address>(ucontext->sc_esp);
460 state.fp =
reinterpret_cast<Address>(ucontext->sc_ebp);
461 #elif V8_HOST_ARCH_X64
462 state.pc =
reinterpret_cast<Address>(ucontext->sc_rip);
463 state.sp =
reinterpret_cast<Address>(ucontext->sc_rsp);
464 state.fp =
reinterpret_cast<Address>(ucontext->sc_rbp);
467 state.pc =
reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
468 state.sp =
reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
469 state.fp =
reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
471 #if V8_HOST_ARCH_IA32
472 state.pc =
reinterpret_cast<Address>(mcontext.cpu.eip);
473 state.sp =
reinterpret_cast<Address>(mcontext.cpu.esp);
474 state.fp =
reinterpret_cast<Address>(mcontext.cpu.ebp);
475 #elif V8_HOST_ARCH_ARM
476 state.pc =
reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]);
477 state.sp =
reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]);
478 state.fp =
reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]);
482 sampler->SampleStack(state);
501 bool need_to_start =
false;
502 base::LockGuard<base::Mutex> lock_guard(
mutex_);
507 need_to_start =
true;
521 base::LockGuard<base::Mutex> lock_guard(
mutex_);
536 if (!instance_to_remove)
return;
537 instance_to_remove->
Join();
538 delete instance_to_remove;
545 base::LockGuard<base::Mutex> lock_guard(
mutex_);
582 timestamp = base::TimeTicks::HighResolutionNow();
584 state = isolate->current_vm_state();
590 if (js_entry_sp == 0) {
595 ExternalCallbackScope* scope = isolate->external_callback_scope();
600 if (scope && scope->scope_address() < handler) {
622 #if defined(USE_SIGNALS)
623 SignalHandler::SetUp();
631 #if defined(USE_SIGNALS)
632 SignalHandler::TearDown();
641 has_processing_thread_(
false),
643 is_counting_samples_(
false),
644 js_and_external_sample_count_(0) {
645 data_ =
new PlatformData;
671 #if defined(USE_SIGNALS)
672 SignalHandler::IncreaseSamplerCount();
678 #if defined(USE_SIGNALS)
679 SignalHandler::DecreaseSamplerCount();
688 if (sample ==
NULL) sample = &sample_obj;
696 if (sample != &sample_obj) {
702 #if defined(USE_SIGNALS)
705 if (!SignalHandler::Installed())
return;
709 #elif V8_OS_WIN || V8_OS_CYGWIN
713 if (profiled_thread ==
NULL)
return;
715 #if defined(USE_SIMULATOR)
716 SimulatorHelper helper;
717 if (!helper.Init(
this,
isolate()))
return;
720 const DWORD kSuspendFailed =
static_cast<DWORD>(-1);
721 if (SuspendThread(profiled_thread) == kSuspendFailed)
return;
725 memset(&context, 0,
sizeof(context));
726 context.ContextFlags = CONTEXT_FULL;
727 if (GetThreadContext(profiled_thread, &context) != 0) {
729 #if defined(USE_SIMULATOR)
730 helper.FillRegisters(&state);
733 state.pc =
reinterpret_cast<Address>(context.Rip);
734 state.sp =
reinterpret_cast<Address>(context.Rsp);
735 state.fp =
reinterpret_cast<Address>(context.Rbp);
737 state.pc =
reinterpret_cast<Address>(context.Eip);
738 state.sp =
reinterpret_cast<Address>(context.Esp);
739 state.fp =
reinterpret_cast<Address>(context.Ebp);
744 ResumeThread(profiled_thread);
static bool IsActive()
Returns whether v8::Locker is being used by this V8 instance.
static void Sleep(const int milliseconds)
Thread(const Options &options)
void StartSynchronously()
TickSample * StartTickSample()
ThreadLocalTop * thread_local_top()
static Address handler(ThreadLocalTop *thread)
CpuProfiler * cpu_profiler() const
static Address & Address_at(Address addr)
StackFrame * frame() const
StackFrame::Type top_frame_type() const
static base::Mutex * mutex_
static void AddActiveSampler(Sampler *sampler)
static void RemoveActiveSampler(Sampler *sampler)
SamplerThread(int interval)
List< Sampler * > active_samplers_
DISALLOW_COPY_AND_ASSIGN(SamplerThread)
static SamplerThread * instance_
static const int kSamplerThreadStackSize
PlatformData * platform_data() const
Sampler(Isolate *isolate, int interval)
virtual void Tick(TickSample *sample)=0
void SetActive(bool value)
void DecreaseProfilingDepth()
base::Atomic32 profiling_
bool is_counting_samples_
void SampleStack(const RegisterState ®s)
void IncreaseProfilingDepth()
Isolate * isolate() const
unsigned js_and_external_sample_count_
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
typedef HANDLE(__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))(DWORD dwFlags
Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr, Atomic32 increment)
typedef DWORD(__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID)
Debugger support for the V8 JavaScript engine.
Address external_callback
StackFrame::Type top_frame_type
base::TimeTicks timestamp
Address stack[kMaxFramesCount]
bool has_external_callback
void Init(Isolate *isolate, const RegisterState &state)
static const unsigned kMaxFramesCount