OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 } | 224 } |
225 | 225 |
226 HANDLE profiled_thread() { return profiled_thread_; } | 226 HANDLE profiled_thread() { return profiled_thread_; } |
227 | 227 |
228 private: | 228 private: |
229 HANDLE profiled_thread_; | 229 HANDLE profiled_thread_; |
230 }; | 230 }; |
231 #endif | 231 #endif |
232 | 232 |
233 | 233 |
234 class SampleHelper { | 234 #if defined(USE_SIMULATOR) |
| 235 class SimulatorHelper { |
235 public: | 236 public: |
236 inline TickSample* Init(Sampler* sampler, Isolate* isolate) { | 237 inline bool Init(Sampler* sampler, Isolate* isolate) { |
237 #if defined(USE_SIMULATOR) | |
238 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); | 238 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); |
239 Isolate::PerIsolateThreadData* per_thread_data = isolate-> | 239 Isolate::PerIsolateThreadData* per_thread_data = isolate-> |
240 FindPerThreadDataForThread(thread_id); | 240 FindPerThreadDataForThread(thread_id); |
241 if (!per_thread_data) return NULL; | 241 if (!per_thread_data) return false; |
242 simulator_ = per_thread_data->simulator(); | 242 simulator_ = per_thread_data->simulator(); |
243 // Check if there is active simulator before allocating TickSample. | 243 // Check if there is active simulator. |
244 if (!simulator_) return NULL; | 244 return simulator_ != NULL; |
245 #endif // USE_SIMULATOR | |
246 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent(); | |
247 if (sample == NULL) sample = &sample_obj; | |
248 return sample; | |
249 } | 245 } |
250 | 246 |
251 #if defined(USE_SIMULATOR) | 247 inline void FillRegisters(RegisterState* state) { |
252 inline void FillRegisters(TickSample* sample) { | 248 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); |
253 sample->pc = reinterpret_cast<Address>(simulator_->get_pc()); | 249 state->sp = reinterpret_cast<Address>(simulator_->get_register( |
254 sample->sp = reinterpret_cast<Address>(simulator_->get_register( | |
255 Simulator::sp)); | 250 Simulator::sp)); |
256 #if V8_TARGET_ARCH_ARM | 251 #if V8_TARGET_ARCH_ARM |
257 sample->fp = reinterpret_cast<Address>(simulator_->get_register( | 252 state->fp = reinterpret_cast<Address>(simulator_->get_register( |
258 Simulator::r11)); | 253 Simulator::r11)); |
259 #elif V8_TARGET_ARCH_MIPS | 254 #elif V8_TARGET_ARCH_MIPS |
260 sample->fp = reinterpret_cast<Address>(simulator_->get_register( | 255 state->fp = reinterpret_cast<Address>(simulator_->get_register( |
261 Simulator::fp)); | 256 Simulator::fp)); |
262 #endif | 257 #endif |
263 } | 258 } |
264 #endif // USE_SIMULATOR | |
265 | 259 |
266 private: | 260 private: |
267 #if defined(USE_SIMULATOR) | |
268 Simulator* simulator_; | 261 Simulator* simulator_; |
269 #endif | |
270 TickSample sample_obj; | |
271 }; | 262 }; |
| 263 #endif // USE_SIMULATOR |
272 | 264 |
273 | 265 |
274 #if defined(USE_SIGNALS) | 266 #if defined(USE_SIGNALS) |
275 | 267 |
276 class SignalHandler : public AllStatic { | 268 class SignalHandler : public AllStatic { |
277 public: | 269 public: |
278 static inline void EnsureInstalled() { | 270 static inline void EnsureInstalled() { |
279 if (signal_handler_installed_) return; | 271 if (signal_handler_installed_) return; |
280 struct sigaction sa; | 272 struct sigaction sa; |
281 sa.sa_sigaction = &HandleProfilerSignal; | 273 sa.sa_sigaction = &HandleProfilerSignal; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 return; | 313 return; |
322 } | 314 } |
323 if (v8::Locker::IsActive() && | 315 if (v8::Locker::IsActive() && |
324 !isolate->thread_manager()->IsLockedByCurrentThread()) { | 316 !isolate->thread_manager()->IsLockedByCurrentThread()) { |
325 return; | 317 return; |
326 } | 318 } |
327 | 319 |
328 Sampler* sampler = isolate->logger()->sampler(); | 320 Sampler* sampler = isolate->logger()->sampler(); |
329 if (sampler == NULL || !sampler->IsActive()) return; | 321 if (sampler == NULL || !sampler->IsActive()) return; |
330 | 322 |
331 SampleHelper helper; | 323 RegisterState state; |
332 TickSample* sample = helper.Init(sampler, isolate); | |
333 if (sample == NULL) return; | |
334 | 324 |
335 #if defined(USE_SIMULATOR) | 325 #if defined(USE_SIMULATOR) |
336 helper.FillRegisters(sample); | 326 SimulatorHelper helper; |
| 327 if (!helper.Init(sampler, isolate)) return; |
| 328 helper.FillRegisters(&state); |
337 #else | 329 #else |
338 // Extracting the sample from the context is extremely machine dependent. | 330 // Extracting the sample from the context is extremely machine dependent. |
339 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); | 331 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); |
340 mcontext_t& mcontext = ucontext->uc_mcontext; | 332 mcontext_t& mcontext = ucontext->uc_mcontext; |
341 sample->state = isolate->current_vm_state(); | |
342 #if defined(__linux__) || defined(__ANDROID__) | 333 #if defined(__linux__) || defined(__ANDROID__) |
343 #if V8_HOST_ARCH_IA32 | 334 #if V8_HOST_ARCH_IA32 |
344 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); | 335 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); |
345 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); | 336 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); |
346 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); | 337 state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); |
347 #elif V8_HOST_ARCH_X64 | 338 #elif V8_HOST_ARCH_X64 |
348 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); | 339 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); |
349 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); | 340 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); |
350 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); | 341 state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); |
351 #elif V8_HOST_ARCH_ARM | 342 #elif V8_HOST_ARCH_ARM |
352 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \ | 343 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \ |
353 (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) | 344 (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
354 // Old GLibc ARM versions used a gregs[] array to access the register | 345 // Old GLibc ARM versions used a gregs[] array to access the register |
355 // values from mcontext_t. | 346 // values from mcontext_t. |
356 sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]); | 347 state.pc = reinterpret_cast<Address>(mcontext.gregs[R15]); |
357 sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]); | 348 state.sp = reinterpret_cast<Address>(mcontext.gregs[R13]); |
358 sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]); | 349 state.fp = reinterpret_cast<Address>(mcontext.gregs[R11]); |
359 #else | 350 #else |
360 sample->pc = reinterpret_cast<Address>(mcontext.arm_pc); | 351 state.pc = reinterpret_cast<Address>(mcontext.arm_pc); |
361 sample->sp = reinterpret_cast<Address>(mcontext.arm_sp); | 352 state.sp = reinterpret_cast<Address>(mcontext.arm_sp); |
362 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp); | 353 state.fp = reinterpret_cast<Address>(mcontext.arm_fp); |
363 #endif // defined(__GLIBC__) && !defined(__UCLIBC__) && | 354 #endif // defined(__GLIBC__) && !defined(__UCLIBC__) && |
364 // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) | 355 // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
365 #elif V8_HOST_ARCH_MIPS | 356 #elif V8_HOST_ARCH_MIPS |
366 sample->pc = reinterpret_cast<Address>(mcontext.pc); | 357 state.pc = reinterpret_cast<Address>(mcontext.pc); |
367 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); | 358 state.sp = reinterpret_cast<Address>(mcontext.gregs[29]); |
368 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); | 359 state.fp = reinterpret_cast<Address>(mcontext.gregs[30]); |
369 #endif // V8_HOST_ARCH_* | 360 #endif // V8_HOST_ARCH_* |
370 #elif defined(__FreeBSD__) | 361 #elif defined(__FreeBSD__) |
371 #if V8_HOST_ARCH_IA32 | 362 #if V8_HOST_ARCH_IA32 |
372 sample->pc = reinterpret_cast<Address>(mcontext.mc_eip); | 363 state.pc = reinterpret_cast<Address>(mcontext.mc_eip); |
373 sample->sp = reinterpret_cast<Address>(mcontext.mc_esp); | 364 state.sp = reinterpret_cast<Address>(mcontext.mc_esp); |
374 sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp); | 365 state.fp = reinterpret_cast<Address>(mcontext.mc_ebp); |
375 #elif V8_HOST_ARCH_X64 | 366 #elif V8_HOST_ARCH_X64 |
376 sample->pc = reinterpret_cast<Address>(mcontext.mc_rip); | 367 state.pc = reinterpret_cast<Address>(mcontext.mc_rip); |
377 sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp); | 368 state.sp = reinterpret_cast<Address>(mcontext.mc_rsp); |
378 sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp); | 369 state.fp = reinterpret_cast<Address>(mcontext.mc_rbp); |
379 #elif V8_HOST_ARCH_ARM | 370 #elif V8_HOST_ARCH_ARM |
380 sample->pc = reinterpret_cast<Address>(mcontext.mc_r15); | 371 state.pc = reinterpret_cast<Address>(mcontext.mc_r15); |
381 sample->sp = reinterpret_cast<Address>(mcontext.mc_r13); | 372 state.sp = reinterpret_cast<Address>(mcontext.mc_r13); |
382 sample->fp = reinterpret_cast<Address>(mcontext.mc_r11); | 373 state.fp = reinterpret_cast<Address>(mcontext.mc_r11); |
383 #endif // V8_HOST_ARCH_* | 374 #endif // V8_HOST_ARCH_* |
384 #elif defined(__NetBSD__) | 375 #elif defined(__NetBSD__) |
385 #if V8_HOST_ARCH_IA32 | 376 #if V8_HOST_ARCH_IA32 |
386 sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]); | 377 state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]); |
387 sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]); | 378 state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]); |
388 sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]); | 379 state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]); |
389 #elif V8_HOST_ARCH_X64 | 380 #elif V8_HOST_ARCH_X64 |
390 sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]); | 381 state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]); |
391 sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]); | 382 state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]); |
392 sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]); | 383 state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]); |
393 #endif // V8_HOST_ARCH_* | 384 #endif // V8_HOST_ARCH_* |
394 #elif defined(__OpenBSD__) | 385 #elif defined(__OpenBSD__) |
395 USE(mcontext); | 386 USE(mcontext); |
396 #if V8_HOST_ARCH_IA32 | 387 #if V8_HOST_ARCH_IA32 |
397 sample->pc = reinterpret_cast<Address>(ucontext->sc_eip); | 388 state.pc = reinterpret_cast<Address>(ucontext->sc_eip); |
398 sample->sp = reinterpret_cast<Address>(ucontext->sc_esp); | 389 state.sp = reinterpret_cast<Address>(ucontext->sc_esp); |
399 sample->fp = reinterpret_cast<Address>(ucontext->sc_ebp); | 390 state.fp = reinterpret_cast<Address>(ucontext->sc_ebp); |
400 #elif V8_HOST_ARCH_X64 | 391 #elif V8_HOST_ARCH_X64 |
401 sample->pc = reinterpret_cast<Address>(ucontext->sc_rip); | 392 state.pc = reinterpret_cast<Address>(ucontext->sc_rip); |
402 sample->sp = reinterpret_cast<Address>(ucontext->sc_rsp); | 393 state.sp = reinterpret_cast<Address>(ucontext->sc_rsp); |
403 sample->fp = reinterpret_cast<Address>(ucontext->sc_rbp); | 394 state.fp = reinterpret_cast<Address>(ucontext->sc_rbp); |
404 #endif // V8_HOST_ARCH_* | 395 #endif // V8_HOST_ARCH_* |
405 #elif defined(__sun) | 396 #elif defined(__sun) |
406 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]); | 397 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]); |
407 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); | 398 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); |
408 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); | 399 state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); |
409 #endif // __sun | 400 #endif // __sun |
410 #endif // USE_SIMULATOR | 401 #endif // USE_SIMULATOR |
411 | 402 sampler->SampleStack(state); |
412 sampler->SampleStack(sample); | |
413 sampler->Tick(sample); | |
414 #endif // __native_client__ | 403 #endif // __native_client__ |
415 } | 404 } |
416 | 405 |
417 #endif | 406 #endif |
418 | 407 |
419 | 408 |
420 class SamplerThread : public Thread { | 409 class SamplerThread : public Thread { |
421 public: | 410 public: |
422 static const int kSamplerThreadStackSize = 64 * KB; | 411 static const int kSamplerThreadStackSize = 64 * KB; |
423 | 412 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 pthread_t tid = sampler->platform_data()->vm_tid(); | 491 pthread_t tid = sampler->platform_data()->vm_tid(); |
503 pthread_kill(tid, SIGPROF); | 492 pthread_kill(tid, SIGPROF); |
504 } | 493 } |
505 | 494 |
506 #elif defined(__MACH__) | 495 #elif defined(__MACH__) |
507 | 496 |
508 void SampleContext(Sampler* sampler) { | 497 void SampleContext(Sampler* sampler) { |
509 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); | 498 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); |
510 Isolate* isolate = sampler->isolate(); | 499 Isolate* isolate = sampler->isolate(); |
511 | 500 |
512 SampleHelper helper; | 501 #if defined(USE_SIMULATOR) |
513 TickSample* sample = helper.Init(sampler, isolate); | 502 SimulatorHelper helper; |
514 if (sample == NULL) return; | 503 if (!helper.Init(sampler, isolate)) return; |
| 504 #endif |
515 | 505 |
516 if (KERN_SUCCESS != thread_suspend(profiled_thread)) return; | 506 if (KERN_SUCCESS != thread_suspend(profiled_thread)) return; |
517 | 507 |
518 #if V8_HOST_ARCH_X64 | 508 #if V8_HOST_ARCH_X64 |
519 thread_state_flavor_t flavor = x86_THREAD_STATE64; | 509 thread_state_flavor_t flavor = x86_THREAD_STATE64; |
520 x86_thread_state64_t state; | 510 x86_thread_state64_t state; |
521 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; | 511 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; |
522 #if __DARWIN_UNIX03 | 512 #if __DARWIN_UNIX03 |
523 #define REGISTER_FIELD(name) __r ## name | 513 #define REGISTER_FIELD(name) __r ## name |
524 #else | 514 #else |
525 #define REGISTER_FIELD(name) r ## name | 515 #define REGISTER_FIELD(name) r ## name |
526 #endif // __DARWIN_UNIX03 | 516 #endif // __DARWIN_UNIX03 |
527 #elif V8_HOST_ARCH_IA32 | 517 #elif V8_HOST_ARCH_IA32 |
528 thread_state_flavor_t flavor = i386_THREAD_STATE; | 518 thread_state_flavor_t flavor = i386_THREAD_STATE; |
529 i386_thread_state_t state; | 519 i386_thread_state_t state; |
530 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT; | 520 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT; |
531 #if __DARWIN_UNIX03 | 521 #if __DARWIN_UNIX03 |
532 #define REGISTER_FIELD(name) __e ## name | 522 #define REGISTER_FIELD(name) __e ## name |
533 #else | 523 #else |
534 #define REGISTER_FIELD(name) e ## name | 524 #define REGISTER_FIELD(name) e ## name |
535 #endif // __DARWIN_UNIX03 | 525 #endif // __DARWIN_UNIX03 |
536 #else | 526 #else |
537 #error Unsupported Mac OS X host architecture. | 527 #error Unsupported Mac OS X host architecture. |
538 #endif // V8_HOST_ARCH | 528 #endif // V8_HOST_ARCH |
539 | 529 |
540 if (thread_get_state(profiled_thread, | 530 if (thread_get_state(profiled_thread, |
541 flavor, | 531 flavor, |
542 reinterpret_cast<natural_t*>(&state), | 532 reinterpret_cast<natural_t*>(&state), |
543 &count) == KERN_SUCCESS) { | 533 &count) == KERN_SUCCESS) { |
544 sample->state = isolate->current_vm_state(); | 534 RegisterState state; |
545 #if defined(USE_SIMULATOR) | 535 #if defined(USE_SIMULATOR) |
546 helper.FillRegisters(sample); | 536 helper.FillRegisters(&state); |
547 #else | 537 #else |
548 sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip)); | 538 state.pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip)); |
549 sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); | 539 state.sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); |
550 sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); | 540 state.fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); |
551 #endif // USE_SIMULATOR | 541 #endif // USE_SIMULATOR |
552 #undef REGISTER_FIELD | 542 #undef REGISTER_FIELD |
553 sampler->SampleStack(sample); | 543 sampler->SampleStack(state); |
554 sampler->Tick(sample); | |
555 } | 544 } |
556 thread_resume(profiled_thread); | 545 thread_resume(profiled_thread); |
557 } | 546 } |
558 | 547 |
559 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) | 548 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) |
560 | 549 |
561 void SampleContext(Sampler* sampler) { | 550 void SampleContext(Sampler* sampler) { |
562 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); | 551 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); |
563 if (profiled_thread == NULL) return; | 552 if (profiled_thread == NULL) return; |
564 | 553 |
565 Isolate* isolate = sampler->isolate(); | 554 Isolate* isolate = sampler->isolate(); |
566 SampleHelper helper; | 555 #if defined(USE_SIMULATOR) |
567 TickSample* sample = helper.Init(sampler, isolate); | 556 SimulatorHelper helper; |
568 if (sample == NULL) return; | 557 if (!helper.Init(sampler, isolate)) return; |
| 558 #endif |
569 | 559 |
570 const DWORD kSuspendFailed = static_cast<DWORD>(-1); | 560 const DWORD kSuspendFailed = static_cast<DWORD>(-1); |
571 if (SuspendThread(profiled_thread) == kSuspendFailed) return; | 561 if (SuspendThread(profiled_thread) == kSuspendFailed) return; |
572 sample->state = isolate->current_vm_state(); | |
573 | 562 |
574 // Context used for sampling the register state of the profiled thread. | 563 // Context used for sampling the register state of the profiled thread. |
575 CONTEXT context; | 564 CONTEXT context; |
576 memset(&context, 0, sizeof(context)); | 565 memset(&context, 0, sizeof(context)); |
577 context.ContextFlags = CONTEXT_FULL; | 566 context.ContextFlags = CONTEXT_FULL; |
578 if (GetThreadContext(profiled_thread, &context) != 0) { | 567 if (GetThreadContext(profiled_thread, &context) != 0) { |
| 568 RegisterState state; |
579 #if defined(USE_SIMULATOR) | 569 #if defined(USE_SIMULATOR) |
580 helper.FillRegisters(sample); | 570 helper.FillRegisters(&state); |
581 #else | 571 #else |
582 #if V8_HOST_ARCH_X64 | 572 #if V8_HOST_ARCH_X64 |
583 sample->pc = reinterpret_cast<Address>(context.Rip); | 573 state.pc = reinterpret_cast<Address>(context.Rip); |
584 sample->sp = reinterpret_cast<Address>(context.Rsp); | 574 state.sp = reinterpret_cast<Address>(context.Rsp); |
585 sample->fp = reinterpret_cast<Address>(context.Rbp); | 575 state.fp = reinterpret_cast<Address>(context.Rbp); |
586 #else | 576 #else |
587 sample->pc = reinterpret_cast<Address>(context.Eip); | 577 state.pc = reinterpret_cast<Address>(context.Eip); |
588 sample->sp = reinterpret_cast<Address>(context.Esp); | 578 state.sp = reinterpret_cast<Address>(context.Esp); |
589 sample->fp = reinterpret_cast<Address>(context.Ebp); | 579 state.fp = reinterpret_cast<Address>(context.Ebp); |
590 #endif | 580 #endif |
591 #endif // USE_SIMULATOR | 581 #endif // USE_SIMULATOR |
592 sampler->SampleStack(sample); | 582 sampler->SampleStack(state); |
593 sampler->Tick(sample); | |
594 } | 583 } |
595 ResumeThread(profiled_thread); | 584 ResumeThread(profiled_thread); |
596 } | 585 } |
597 | 586 |
598 #endif // USE_SIGNALS | 587 #endif // USE_SIGNALS |
599 | 588 |
600 | 589 |
601 // Protects the process wide state below. | 590 // Protects the process wide state below. |
602 static Mutex* mutex_; | 591 static Mutex* mutex_; |
603 static SamplerThread* instance_; | 592 static SamplerThread* instance_; |
604 | 593 |
605 const int interval_; | 594 const int interval_; |
606 List<Sampler*> active_samplers_; | 595 List<Sampler*> active_samplers_; |
607 | 596 |
608 DISALLOW_COPY_AND_ASSIGN(SamplerThread); | 597 DISALLOW_COPY_AND_ASSIGN(SamplerThread); |
609 }; | 598 }; |
610 | 599 |
611 | 600 |
612 Mutex* SamplerThread::mutex_ = NULL; | 601 Mutex* SamplerThread::mutex_ = NULL; |
613 SamplerThread* SamplerThread::instance_ = NULL; | 602 SamplerThread* SamplerThread::instance_ = NULL; |
614 | 603 |
615 | 604 |
616 // | 605 // |
617 // StackTracer implementation | 606 // StackTracer implementation |
618 // | 607 // |
619 DISABLE_ASAN void TickSample::Trace(Isolate* isolate) { | 608 DISABLE_ASAN void TickSample::Init(Isolate* isolate, |
| 609 const RegisterState& regs) { |
620 ASSERT(isolate->IsInitialized()); | 610 ASSERT(isolate->IsInitialized()); |
| 611 pc = regs.pc; |
| 612 state = isolate->current_vm_state(); |
621 | 613 |
622 // Avoid collecting traces while doing GC. | 614 // Avoid collecting traces while doing GC. |
623 if (state == GC) return; | 615 if (state == GC) return; |
624 | 616 |
625 const Address js_entry_sp = | 617 const Address js_entry_sp = |
626 Isolate::js_entry_sp(isolate->thread_local_top()); | 618 Isolate::js_entry_sp(isolate->thread_local_top()); |
627 if (js_entry_sp == 0) { | 619 if (js_entry_sp == 0) { |
628 // Not executing JS now. | 620 // Not executing JS now. |
629 return; | 621 return; |
630 } | 622 } |
631 | 623 |
632 const Address callback = isolate->external_callback(); | 624 const Address callback = isolate->external_callback(); |
633 if (callback != NULL) { | 625 if (callback != NULL) { |
634 external_callback = callback; | 626 external_callback = callback; |
635 has_external_callback = true; | 627 has_external_callback = true; |
636 } else { | 628 } else { |
637 // Sample potential return address value for frameless invocation of | 629 // Sample potential return address value for frameless invocation of |
638 // stubs (we'll figure out later, if this value makes sense). | 630 // stubs (we'll figure out later, if this value makes sense). |
639 tos = Memory::Address_at(sp); | 631 tos = Memory::Address_at(regs.sp); |
640 has_external_callback = false; | 632 has_external_callback = false; |
641 } | 633 } |
642 | 634 |
643 SafeStackFrameIterator it(isolate, fp, sp, sp, js_entry_sp); | 635 SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp); |
644 top_frame_type = it.top_frame_type(); | 636 top_frame_type = it.top_frame_type(); |
645 int i = 0; | 637 int i = 0; |
646 while (!it.done() && i < TickSample::kMaxFramesCount) { | 638 while (!it.done() && i < TickSample::kMaxFramesCount) { |
647 stack[i++] = it.frame()->pc(); | 639 stack[i++] = it.frame()->pc(); |
648 it.Advance(); | 640 it.Advance(); |
649 } | 641 } |
650 frames_count = i; | 642 frames_count = i; |
651 } | 643 } |
652 | 644 |
653 | 645 |
(...skipping 28 matching lines...) Expand all Loading... |
682 SamplerThread::AddActiveSampler(this); | 674 SamplerThread::AddActiveSampler(this); |
683 } | 675 } |
684 | 676 |
685 | 677 |
686 void Sampler::Stop() { | 678 void Sampler::Stop() { |
687 ASSERT(IsActive()); | 679 ASSERT(IsActive()); |
688 SamplerThread::RemoveActiveSampler(this); | 680 SamplerThread::RemoveActiveSampler(this); |
689 SetActive(false); | 681 SetActive(false); |
690 } | 682 } |
691 | 683 |
692 void Sampler::SampleStack(TickSample* sample) { | 684 void Sampler::SampleStack(const RegisterState& state) { |
693 sample->Trace(isolate_); | 685 TickSample* sample = isolate_->cpu_profiler()->TickSampleEvent(); |
| 686 TickSample sample_obj; |
| 687 if (sample == NULL) sample = &sample_obj; |
| 688 sample->Init(isolate_, state); |
694 if (++samples_taken_ < 0) samples_taken_ = 0; | 689 if (++samples_taken_ < 0) samples_taken_ = 0; |
| 690 Tick(sample); |
695 } | 691 } |
696 | 692 |
697 } } // namespace v8::internal | 693 } } // namespace v8::internal |
OLD | NEW |