 Chromium Code Reviews
 Chromium Code Reviews Issue 422593003:
  Initial GetSample implementation.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 422593003:
  Initial GetSample implementation.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| OLD | NEW | 
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | |
| 5 #include "src/sampler.h" | 4 #include "src/sampler.h" | 
| 6 | 5 | 
| 7 #if V8_OS_POSIX && !V8_OS_CYGWIN | 6 #if V8_OS_POSIX && !V8_OS_CYGWIN | 
| 8 | 7 | 
| 9 #define USE_SIGNALS | 8 #define USE_SIGNALS | 
| 10 | 9 | 
| 11 #include <errno.h> | 10 #include <errno.h> | 
| 12 #include <pthread.h> | 11 #include <pthread.h> | 
| 13 #include <signal.h> | 12 #include <signal.h> | 
| 14 #include <sys/time.h> | 13 #include <sys/time.h> | 
| (...skipping 20 matching lines...) Expand all Loading... | |
| 35 !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT) | 34 !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT) | 
| 36 #include <asm/sigcontext.h> // NOLINT | 35 #include <asm/sigcontext.h> // NOLINT | 
| 37 #endif | 36 #endif | 
| 38 | 37 | 
| 39 #elif V8_OS_WIN || V8_OS_CYGWIN | 38 #elif V8_OS_WIN || V8_OS_CYGWIN | 
| 40 | 39 | 
| 41 #include "src/base/win32-headers.h" | 40 #include "src/base/win32-headers.h" | 
| 42 | 41 | 
| 43 #endif | 42 #endif | 
| 44 | 43 | 
| 44 #include "include/v8-sampler.h" | |
| 45 | |
| 45 #include "src/v8.h" | 46 #include "src/v8.h" | 
| 46 | 47 | 
| 47 #include "src/base/platform/platform.h" | 48 #include "src/base/platform/platform.h" | 
| 48 #include "src/cpu-profiler-inl.h" | 49 #include "src/cpu-profiler-inl.h" | 
| 49 #include "src/flags.h" | 50 #include "src/flags.h" | 
| 50 #include "src/frames-inl.h" | 51 #include "src/frames-inl.h" | 
| 51 #include "src/log.h" | 52 #include "src/log.h" | 
| 52 #include "src/simulator.h" | 53 #include "src/simulator.h" | 
| 53 #include "src/v8threads.h" | 54 #include "src/v8threads.h" | 
| 54 #include "src/vm-state-inl.h" | 55 #include "src/vm-state-inl.h" | 
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 private: | 263 private: | 
| 263 Simulator* simulator_; | 264 Simulator* simulator_; | 
| 264 }; | 265 }; | 
| 265 #endif // USE_SIMULATOR | 266 #endif // USE_SIMULATOR | 
| 266 | 267 | 
| 267 | 268 | 
| 268 #if defined(USE_SIGNALS) | 269 #if defined(USE_SIGNALS) | 
| 269 | 270 | 
| 270 class SignalHandler : public AllStatic { | 271 class SignalHandler : public AllStatic { | 
| 271 public: | 272 public: | 
| 272 static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); } | 273 static void SetUp() { | 
| 273 static void TearDown() { delete mutex_; } | 274 if (!mutex_) mutex_ = new base::Mutex(); | 
| 275 if (!new_sample_semaphore_) | |
| 276 new_sample_semaphore_ = new base::Semaphore(0); | |
| 277 } | |
| 278 | |
| 279 static void TearDown() { | |
| 280 delete mutex_; | |
| 281 delete new_sample_semaphore_; | |
| 282 } | |
| 274 | 283 | 
| 275 static void IncreaseSamplerCount() { | 284 static void IncreaseSamplerCount() { | 
| 276 base::LockGuard<base::Mutex> lock_guard(mutex_); | 285 base::LockGuard<base::Mutex> lock_guard(mutex_); | 
| 277 if (++client_count_ == 1) Install(); | 286 if (++client_count_ == 1) Install(); | 
| 278 } | 287 } | 
| 279 | 288 | 
| 280 static void DecreaseSamplerCount() { | 289 static void DecreaseSamplerCount() { | 
| 281 base::LockGuard<base::Mutex> lock_guard(mutex_); | 290 base::LockGuard<base::Mutex> lock_guard(mutex_); | 
| 282 if (--client_count_ == 0) Restore(); | 291 if (--client_count_ == 0) Restore(); | 
| 283 } | 292 } | 
| 284 | 293 | 
| 285 static bool Installed() { | 294 static bool Installed() { | 
| 286 return signal_handler_installed_; | 295 return signal_handler_installed_; | 
| 287 } | 296 } | 
| 288 | 297 | 
| 298 | |
| 
fmeawad
2014/07/29 18:30:50
Delete the added line.
 
gholap
2014/07/29 23:25:20
Done.
 | |
| 289 private: | 299 private: | 
| 290 static void Install() { | 300 static void Install() { | 
| 291 struct sigaction sa; | 301 struct sigaction sa; | 
| 292 sa.sa_sigaction = &HandleProfilerSignal; | 302 sa.sa_sigaction = &HandleProfilerSignal; | 
| 293 sigemptyset(&sa.sa_mask); | 303 sigemptyset(&sa.sa_mask); | 
| 294 #if V8_OS_QNX | 304 #if V8_OS_QNX | 
| 295 sa.sa_flags = SA_SIGINFO; | 305 sa.sa_flags = SA_SIGINFO; | 
| 296 #else | 306 #else | 
| 297 sa.sa_flags = SA_RESTART | SA_SIGINFO; | 307 sa.sa_flags = SA_RESTART | SA_SIGINFO; | 
| 298 #endif | 308 #endif | 
| 299 signal_handler_installed_ = | 309 signal_handler_installed_ = | 
| 300 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); | 310 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); | 
| 301 } | 311 } | 
| 302 | 312 | 
| 303 static void Restore() { | 313 static void Restore() { | 
| 304 if (signal_handler_installed_) { | 314 if (signal_handler_installed_) { | 
| 305 sigaction(SIGPROF, &old_signal_handler_, 0); | 315 sigaction(SIGPROF, &old_signal_handler_, 0); | 
| 306 signal_handler_installed_ = false; | 316 signal_handler_installed_ = false; | 
| 307 } | 317 } | 
| 308 } | 318 } | 
| 309 | 319 | 
| 310 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); | 320 static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); | 
| 321 | |
| 322 // The SIGPROF could have come from DoSample or from GetSample. | |
| 323 // GetSample is the internal endpoint for the public | |
| 324 // GetSample API, which aims to bypass all the internal buffers | |
| 325 // and return just one sample instead, rightaway. | |
| 
fmeawad
2014/07/29 18:30:50
Add a TODO that we will eventually have GetSample,
 
gholap
2014/07/29 23:25:20
Done.
 | |
| 326 | |
| 327 // This is the sample which will be filled by the call from GetSample. | |
| 328 static TickSample sample_; | |
| 329 | |
| 330 // For the SIGPROF handler to know whether the call was from GetSample. | |
| 331 static bool called_from_get_sample_; | |
| 332 | |
| 333 // GetSample waits synchronously till the SIGPROF handler returns. | |
| 334 // this semaphore is used to signal GetSample. | |
| 335 static base::Semaphore* new_sample_semaphore_; | |
| 
fmeawad
2014/07/29 18:30:50
I would call it, sampling_semaphore instead.
 
gholap
2014/07/29 23:25:20
Done.
 | |
| 336 | |
| 337 // It is not that every time HandleProfilerSignal is invoked, | |
| 338 // it succeeds in obtaining a sample. | |
| 339 // This provides GetSample with the information whether | |
| 340 // the handler finished with or without getting the sample. | |
| 341 static bool new_sample_available_; | |
| 
fmeawad
2014/07/29 18:30:50
just sample_available_
 
gholap
2014/07/29 23:25:20
Done.
 | |
| 342 | |
| 311 // Protects the process wide state below. | 343 // Protects the process wide state below. | 
| 312 static base::Mutex* mutex_; | 344 static base::Mutex* mutex_; | 
| 313 static int client_count_; | 345 static int client_count_; | 
| 314 static bool signal_handler_installed_; | 346 static bool signal_handler_installed_; | 
| 315 static struct sigaction old_signal_handler_; | 347 static struct sigaction old_signal_handler_; | 
| 348 | |
| 349 friend class Sampler; | |
| 316 }; | 350 }; | 
| 317 | 351 | 
| 318 | 352 | 
| 353 TickSample SignalHandler::sample_; | |
| 354 bool SignalHandler::called_from_get_sample_ = false; | |
| 355 base::Semaphore* SignalHandler::new_sample_semaphore_ = NULL; | |
| 356 bool SignalHandler::new_sample_available_ = false; | |
| 357 | |
| 319 base::Mutex* SignalHandler::mutex_ = NULL; | 358 base::Mutex* SignalHandler::mutex_ = NULL; | 
| 320 int SignalHandler::client_count_ = 0; | 359 int SignalHandler::client_count_ = 0; | 
| 321 struct sigaction SignalHandler::old_signal_handler_; | 360 struct sigaction SignalHandler::old_signal_handler_; | 
| 322 bool SignalHandler::signal_handler_installed_ = false; | 361 bool SignalHandler::signal_handler_installed_ = false; | 
| 323 | 362 | 
| 324 | 363 | 
| 325 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, | 364 void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, | 
| 326 void* context) { | 365 void* context) { | 
| 327 #if V8_OS_NACL | 366 #if V8_OS_NACL | 
| 328 // As Native Client does not support signal handling, profiling | 367 // As Native Client does not support signal handling, profiling | 
| 329 // is disabled. | 368 // is disabled. | 
| 330 return; | 369 return; | 
| 331 #else | 370 #else | 
| 371 | |
| 372 #define SIGNAL_AND_RETURN(GOT_NEW) \ | |
| 
fmeawad
2014/07/29 18:30:50
Explain why this macro is needed.
 
gholap
2014/07/29 23:25:20
Done.
 | |
| 373 { \ | |
| 374 new_sample_available_ = GOT_NEW; \ | |
| 375 new_sample_semaphore_->Signal(); \ | |
| 376 return; \ | |
| 377 } | |
| 378 | |
| 332 USE(info); | 379 USE(info); | 
| 333 if (signal != SIGPROF) return; | 380 if (signal != SIGPROF) SIGNAL_AND_RETURN(false); | 
| 334 Isolate* isolate = Isolate::UncheckedReentrantCurrent(); | 381 Isolate* isolate = Isolate::UncheckedReentrantCurrent(); | 
| 335 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { | 382 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { | 
| 336 // We require a fully initialized and entered isolate. | 383 // We require a fully initialized and entered isolate. | 
| 337 return; | 384 SIGNAL_AND_RETURN(false); | 
| 338 } | 385 } | 
| 339 if (v8::Locker::IsActive() && | 386 if (v8::Locker::IsActive() && | 
| 340 !isolate->thread_manager()->IsLockedByCurrentThread()) { | 387 !isolate->thread_manager()->IsLockedByCurrentThread()) { | 
| 341 return; | 388 SIGNAL_AND_RETURN(false); | 
| 342 } | 389 } | 
| 343 | 390 | 
| 344 Sampler* sampler = isolate->logger()->sampler(); | 391 Sampler* sampler = isolate->logger()->sampler(); | 
| 345 if (sampler == NULL) return; | 392 if (sampler == NULL) SIGNAL_AND_RETURN(false); | 
| 346 | 393 | 
| 347 RegisterState state; | 394 RegisterState state; | 
| 348 | 395 | 
| 349 #if defined(USE_SIMULATOR) | 396 #if defined(USE_SIMULATOR) | 
| 350 SimulatorHelper helper; | 397 SimulatorHelper helper; | 
| 351 if (!helper.Init(sampler, isolate)) return; | 398 if (!helper.Init(sampler, isolate)) SIGNAL_AND_RETURN(false); | 
| 352 helper.FillRegisters(&state); | 399 helper.FillRegisters(&state); | 
| 353 // It possible that the simulator is interrupted while it is updating | 400 // It possible that the simulator is interrupted while it is updating | 
| 354 // the sp or fp register. ARM64 simulator does this in two steps: | 401 // the sp or fp register. ARM64 simulator does this in two steps: | 
| 355 // first setting it to zero and then setting it to the new value. | 402 // first setting it to zero and then setting it to the new value. | 
| 356 // Bailout if sp/fp doesn't contain the new value. | 403 // Bailout if sp/fp doesn't contain the new value. | 
| 357 if (state.sp == 0 || state.fp == 0) return; | 404 if (state.sp == 0 || state.fp == 0) SIGNAL_AND_RETURN(false); | 
| 358 #else | 405 #else | 
| 359 // Extracting the sample from the context is extremely machine dependent. | 406 // Extracting the sample from the context is extremely machine dependent. | 
| 360 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); | 407 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); | 
| 361 #if !V8_OS_OPENBSD | 408 #if !V8_OS_OPENBSD | 
| 362 mcontext_t& mcontext = ucontext->uc_mcontext; | 409 mcontext_t& mcontext = ucontext->uc_mcontext; | 
| 363 #endif | 410 #endif | 
| 364 #if V8_OS_LINUX | 411 #if V8_OS_LINUX | 
| 365 #if V8_HOST_ARCH_IA32 | 412 #if V8_HOST_ARCH_IA32 | 
| 366 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); | 413 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); | 
| 367 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); | 414 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); | 
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 459 state.pc = reinterpret_cast<Address>(mcontext.cpu.eip); | 506 state.pc = reinterpret_cast<Address>(mcontext.cpu.eip); | 
| 460 state.sp = reinterpret_cast<Address>(mcontext.cpu.esp); | 507 state.sp = reinterpret_cast<Address>(mcontext.cpu.esp); | 
| 461 state.fp = reinterpret_cast<Address>(mcontext.cpu.ebp); | 508 state.fp = reinterpret_cast<Address>(mcontext.cpu.ebp); | 
| 462 #elif V8_HOST_ARCH_ARM | 509 #elif V8_HOST_ARCH_ARM | 
| 463 state.pc = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]); | 510 state.pc = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]); | 
| 464 state.sp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]); | 511 state.sp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]); | 
| 465 state.fp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]); | 512 state.fp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]); | 
| 466 #endif // V8_HOST_ARCH_* | 513 #endif // V8_HOST_ARCH_* | 
| 467 #endif // V8_OS_QNX | 514 #endif // V8_OS_QNX | 
| 468 #endif // USE_SIMULATOR | 515 #endif // USE_SIMULATOR | 
| 469 sampler->SampleStack(state); | 516 if (called_from_get_sample_) { | 
| 517 sample_.Init(sampler->isolate(), state); | |
| 518 } else { | |
| 519 sampler->SampleStack(state); | |
| 520 } | |
| 521 SIGNAL_AND_RETURN(true); | |
| 522 #undef SIGNAL_AND_RETURN | |
| 470 #endif // V8_OS_NACL | 523 #endif // V8_OS_NACL | 
| 471 } | 524 } | 
| 472 | 525 | 
| 473 #endif | 526 #endif | 
| 474 | 527 | 
| 475 | 528 | 
| 476 class SamplerThread : public base::Thread { | 529 class SamplerThread : public base::Thread { | 
| 477 public: | 530 public: | 
| 478 static const int kSamplerThreadStackSize = 64 * KB; | 531 static const int kSamplerThreadStackSize = 64 * KB; | 
| 479 | 532 | 
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 662 | 715 | 
| 663 | 716 | 
| 664 void Sampler::DecreaseProfilingDepth() { | 717 void Sampler::DecreaseProfilingDepth() { | 
| 665 #if defined(USE_SIGNALS) | 718 #if defined(USE_SIGNALS) | 
| 666 SignalHandler::DecreaseSamplerCount(); | 719 SignalHandler::DecreaseSamplerCount(); | 
| 667 #endif | 720 #endif | 
| 668 base::NoBarrier_AtomicIncrement(&profiling_, -1); | 721 base::NoBarrier_AtomicIncrement(&profiling_, -1); | 
| 669 } | 722 } | 
| 670 | 723 | 
| 671 | 724 | 
| 672 void Sampler::SampleStack(const RegisterState& state) { | 725 void Sampler::SampleStack(const RegisterState& state) | 
| 673 TickSample* sample = isolate_->cpu_profiler()->StartTickSample(); | 726 TickSample* sample = isolate_->cpu_profiler()->StartTickSample(); | 
| 674 TickSample sample_obj; | 727 TickSample sample_obj; | 
| 675 if (sample == NULL) sample = &sample_obj; | 728 if (sample == NULL) sample = &sample_obj; | 
| 676 sample->Init(isolate_, state); | 729 sample->Init(isolate_, state); | 
| 677 if (is_counting_samples_) { | 730 if (is_counting_samples_) { | 
| 678 if (sample->state == JS || sample->state == EXTERNAL) { | 731 if (sample->state == JS || sample->state == EXTERNAL) { | 
| 679 ++js_and_external_sample_count_; | 732 ++js_and_external_sample_count_; | 
| 680 } | 733 } | 
| 681 } | 734 } | 
| 682 Tick(sample); | 735 Tick(sample); | 
| 683 if (sample != &sample_obj) { | 736 if (sample != &sample_obj) { | 
| 684 isolate_->cpu_profiler()->FinishTickSample(); | 737 isolate_->cpu_profiler()->FinishTickSample(); | 
| 685 } | 738 } | 
| 686 } | 739 } | 
| 687 | 740 | 
| 688 | 741 | 
| 689 #if defined(USE_SIGNALS) | 742 #if defined(USE_SIGNALS) | 
| 690 | 743 | 
| 691 void Sampler::DoSample() { | 744 void Sampler::DoSample() { | 
| 692 if (!SignalHandler::Installed()) return; | 745 if (!SignalHandler::Installed()) return; | 
| 693 pthread_kill(platform_data()->vm_tid(), SIGPROF); | 746 pthread_kill(platform_data()->vm_tid(), SIGPROF); | 
| 694 } | 747 } | 
| 695 | 748 | 
| 749 | |
| 750 TickSample* Sampler::GetSample(TickSample* sample) { | |
| 751 if (!SignalHandler::Installed()) return NULL; | |
| 752 SignalHandler::called_from_get_sample_ = true; | |
| 753 pthread_kill(platform_data()->vm_tid(), SIGPROF); | |
| 754 SignalHandler::new_sample_semaphore_->Wait(); | |
| 755 if (SignalHandler::new_sample_available_) { | |
| 756 sample->state = SignalHandler::sample_.state; | |
| 757 for (int i = 0; i < SignalHandler::sample_.frames_count; i++) { | |
| 758 sample->stack[i] = SignalHandler::sample_.stack[i]; | |
| 759 } | |
| 760 sample->frames_count = SignalHandler::sample_.frames_count; | |
| 761 } else { | |
| 762 sample = NULL; | |
| 763 } | |
| 764 SignalHandler::called_from_get_sample_ = false; | |
| 765 return sample; | |
| 766 } | |
| 767 | |
| 696 #elif V8_OS_WIN || V8_OS_CYGWIN | 768 #elif V8_OS_WIN || V8_OS_CYGWIN | 
| 697 | 769 | 
| 698 void Sampler::DoSample() { | 770 TickSample* Sampler::GetSampleHelper_(TickSample * sample, | 
| 771 bool called_from_get_sample) { | |
| 699 HANDLE profiled_thread = platform_data()->profiled_thread(); | 772 HANDLE profiled_thread = platform_data()->profiled_thread(); | 
| 700 if (profiled_thread == NULL) return; | 773 if (profiled_thread == NULL) return NULL; | 
| 701 | 774 | 
| 702 #if defined(USE_SIMULATOR) | 775 #if defined(USE_SIMULATOR) | 
| 703 SimulatorHelper helper; | 776 SimulatorHelper helper; | 
| 704 if (!helper.Init(this, isolate())) return; | 777 if (!helper.Init(this, isolate())) return NULL; | 
| 705 #endif | 778 #endif | 
| 706 | 779 | 
| 707 const DWORD kSuspendFailed = static_cast<DWORD>(-1); | 780 const DWORD kSuspendFailed = static_cast<DWORD>(-1); | 
| 708 if (SuspendThread(profiled_thread) == kSuspendFailed) return; | 781 if (SuspendThread(profiled_thread) == kSuspendFailed) return NULL; | 
| 709 | 782 | 
| 710 // Context used for sampling the register state of the profiled thread. | 783 // Context used for sampling the register state of the profiled thread. | 
| 711 CONTEXT context; | 784 CONTEXT context; | 
| 712 memset(&context, 0, sizeof(context)); | 785 memset(&context, 0, sizeof(context)); | 
| 713 context.ContextFlags = CONTEXT_FULL; | 786 context.ContextFlags = CONTEXT_FULL; | 
| 714 if (GetThreadContext(profiled_thread, &context) != 0) { | 787 if (GetThreadContext(profiled_thread, &context) != 0) { | 
| 715 RegisterState state; | 788 RegisterState state; | 
| 716 #if defined(USE_SIMULATOR) | 789 #if defined(USE_SIMULATOR) | 
| 717 helper.FillRegisters(&state); | 790 helper.FillRegisters(&state); | 
| 718 #else | 791 #else | 
| 719 #if V8_HOST_ARCH_X64 | 792 #if V8_HOST_ARCH_X64 | 
| 720 state.pc = reinterpret_cast<Address>(context.Rip); | 793 state.pc = reinterpret_cast<Address>(context.Rip); | 
| 721 state.sp = reinterpret_cast<Address>(context.Rsp); | 794 state.sp = reinterpret_cast<Address>(context.Rsp); | 
| 722 state.fp = reinterpret_cast<Address>(context.Rbp); | 795 state.fp = reinterpret_cast<Address>(context.Rbp); | 
| 723 #else | 796 #else | 
| 724 state.pc = reinterpret_cast<Address>(context.Eip); | 797 state.pc = reinterpret_cast<Address>(context.Eip); | 
| 725 state.sp = reinterpret_cast<Address>(context.Esp); | 798 state.sp = reinterpret_cast<Address>(context.Esp); | 
| 726 state.fp = reinterpret_cast<Address>(context.Ebp); | 799 state.fp = reinterpret_cast<Address>(context.Ebp); | 
| 727 #endif | 800 #endif | 
| 728 #endif // USE_SIMULATOR | 801 #endif // USE_SIMULATOR | 
| 729 SampleStack(state); | 802 if (called_from_get_sample) { | 
| 803 sample->Init(sampler->isolate(), state); | |
| 804 } else { | |
| 805 SampleStack(state); | |
| 806 } | |
| 730 } | 807 } | 
| 731 ResumeThread(profiled_thread); | 808 ResumeThread(profiled_thread); | 
| 809 return sample; | |
| 810 } | |
| 811 | |
| 812 | |
| 813 void Sampler::DoSample() { | |
| 814 GetSampleHelper_(NULL, false); | |
| 815 } | |
| 816 | |
| 817 | |
| 818 TickSample* Sampler::GetSample(TickSample* sample) { | |
| 819 return GetSampleHelper_(sample, true); | |
| 732 } | 820 } | 
| 733 | 821 | 
| 734 #endif // USE_SIGNALS | 822 #endif // USE_SIGNALS | 
| 735 | 823 | 
| 736 | 824 | 
| 737 } } // namespace v8::internal | 825 } } // namespace v8::internal | 
| OLD | NEW |