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