| 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 |