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