Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(885)

Side by Side Diff: src/sampler.cc

Issue 14264009: Merge Windows, Mac OS X and Cygwin sampler implementations with the rest ones (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix Android build Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/platform-win32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ 28 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
29 || defined(__NetBSD__) || defined(__sun) 29 || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__)
30
31 #define USE_SIGNALS
30 32
31 #include <errno.h> 33 #include <errno.h>
32 #include <pthread.h> 34 #include <pthread.h>
33 #include <signal.h> 35 #include <signal.h>
34 #include <sys/time.h> 36 #include <sys/time.h>
35 #include <sys/syscall.h> 37 #include <sys/syscall.h>
38 #if !defined(__ANDROID__) || defined(__BIONIC_HAVE_UCONTEXT_T)
36 #include <ucontext.h> 39 #include <ucontext.h>
40 #endif
37 #include <unistd.h> 41 #include <unistd.h>
38 42
39 #endif
40
41 // GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'. 43 // GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
42 // Old versions of the C library <signal.h> didn't define the type. 44 // Old versions of the C library <signal.h> didn't define the type.
43 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) && \ 45 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
44 defined(__arm__) && !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT) 46 defined(__arm__) && !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
45 #include <asm/sigcontext.h> 47 #include <asm/sigcontext.h>
46 #endif 48 #endif
47 49
50 #elif defined(__MACH__)
51
52 #include <mach/mach.h>
53
54 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
55
56 #include "win32-headers.h"
57
58 #endif
59
48 #include "v8.h" 60 #include "v8.h"
49 61
50 #include "log.h" 62 #include "log.h"
51 #include "platform.h" 63 #include "platform.h"
52 #include "simulator.h" 64 #include "simulator.h"
53 #include "v8threads.h" 65 #include "v8threads.h"
54 66
55 67
56 namespace v8 { 68 namespace v8 {
57 namespace internal { 69 namespace internal {
58 70
59 71
60 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ 72 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
61 || defined(__NetBSD__) || defined(__sun) 73 || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__)
62 74
63 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) 75 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T)
64 76
65 // Not all versions of Android's C library provide ucontext_t. 77 // Not all versions of Android's C library provide ucontext_t.
66 // Detect this and provide custom but compatible definitions. Note that these 78 // Detect this and provide custom but compatible definitions. Note that these
67 // follow the GLibc naming convention to access register values from 79 // follow the GLibc naming convention to access register values from
68 // mcontext_t. 80 // mcontext_t.
69 // 81 //
70 // See http://code.google.com/p/android/issues/detail?id=34784 82 // See http://code.google.com/p/android/issues/detail?id=34784
71 83
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 || defined(__sun) 158 || defined(__sun)
147 return pthread_self(); 159 return pthread_self();
148 #endif 160 #endif
149 } 161 }
150 162
151 163
152 class Sampler::PlatformData : public Malloced { 164 class Sampler::PlatformData : public Malloced {
153 public: 165 public:
154 PlatformData() 166 PlatformData()
155 : vm_tid_(GetThreadID()), 167 : vm_tid_(GetThreadID()),
168 vm_tgid_(getpid()),
156 profiled_thread_id_(ThreadId::Current()) {} 169 profiled_thread_id_(ThreadId::Current()) {}
157 170
158 pthread_t vm_tid() const { return vm_tid_; } 171 pthread_t vm_tid() const { return vm_tid_; }
172 int vm_tgid() const { return vm_tgid_; }
159 ThreadId profiled_thread_id() { return profiled_thread_id_; } 173 ThreadId profiled_thread_id() { return profiled_thread_id_; }
160 174
161 private: 175 private:
162 pthread_t vm_tid_; 176 pthread_t vm_tid_;
177 const int vm_tgid_;
163 ThreadId profiled_thread_id_; 178 ThreadId profiled_thread_id_;
164 }; 179 };
165 180
166 181
167 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 182 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
168 #if defined(__native_client__) 183 #if defined(__native_client__)
169 // As Native Client does not support signal handling, profiling 184 // As Native Client does not support signal handling, profiling
170 // is disabled. 185 // is disabled.
171 return; 186 return;
172 #else 187 #else
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 #elif V8_TARGET_ARCH_MIPS 224 #elif V8_TARGET_ARCH_MIPS
210 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc)); 225 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
211 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp)); 226 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
212 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp)); 227 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
213 #endif // V8_TARGET_ARCH_* 228 #endif // V8_TARGET_ARCH_*
214 #else 229 #else
215 // Extracting the sample from the context is extremely machine dependent. 230 // Extracting the sample from the context is extremely machine dependent.
216 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 231 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
217 mcontext_t& mcontext = ucontext->uc_mcontext; 232 mcontext_t& mcontext = ucontext->uc_mcontext;
218 sample->state = isolate->current_vm_state(); 233 sample->state = isolate->current_vm_state();
219 #if defined(__linux__) 234 #if defined(__linux__) || defined(__ANDROID__)
220 #if V8_HOST_ARCH_IA32 235 #if V8_HOST_ARCH_IA32
221 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); 236 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
222 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); 237 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
223 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); 238 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
224 #elif V8_HOST_ARCH_X64 239 #elif V8_HOST_ARCH_X64
225 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); 240 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
226 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); 241 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
227 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); 242 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
228 #elif V8_HOST_ARCH_ARM 243 #elif V8_HOST_ARCH_ARM
229 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \ 244 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); 299 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
285 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); 300 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
286 #endif // __sun 301 #endif // __sun
287 #endif // USE_SIMULATOR 302 #endif // USE_SIMULATOR
288 303
289 sampler->SampleStack(sample); 304 sampler->SampleStack(sample);
290 sampler->Tick(sample); 305 sampler->Tick(sample);
291 #endif // __native_client__ 306 #endif // __native_client__
292 } 307 }
293 308
309 #elif defined(__MACH__)
310 class Sampler::PlatformData : public Malloced {
311 public:
312 PlatformData()
313 : profiled_thread_(mach_thread_self()),
314 profiled_thread_id_(ThreadId::Current()) {}
294 315
295 class SignalSender : public Thread { 316 ~PlatformData() {
317 // Deallocate Mach port for thread.
318 mach_port_deallocate(mach_task_self(), profiled_thread_);
319 }
320
321 thread_act_t profiled_thread() { return profiled_thread_; }
322 ThreadId profiled_thread_id() { return profiled_thread_id_; }
323
324 private:
325 // Note: for profiled_thread_ Mach primitives are used instead of PThread's
326 // because the latter doesn't provide thread manipulation primitives required.
327 // For details, consult "Mac OS X Internals" book, Section 7.3.
328 thread_act_t profiled_thread_;
329 ThreadId profiled_thread_id_;
330 };
331
332 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
333
334 // ----------------------------------------------------------------------------
335 // Win32 profiler support. On Cygwin we use the same sampler implementation as
336 // on Win32.
337
338 class Sampler::PlatformData : public Malloced {
296 public: 339 public:
297 static const int kSignalSenderStackSize = 64 * KB; 340 // Get a handle to the calling thread. This is the thread that we are
341 // going to profile. We need to make a copy of the handle because we are
342 // going to use it in the sampler thread. Using GetThreadHandle() will
343 // not work in this case. We're using OpenThread because DuplicateHandle
344 // for some reason doesn't work in Chrome's sandbox.
345 PlatformData()
346 : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
347 THREAD_SUSPEND_RESUME |
348 THREAD_QUERY_INFORMATION,
349 false,
350 GetCurrentThreadId())),
351 profiled_thread_id_(ThreadId::Current()) {}
298 352
299 explicit SignalSender(int interval) 353 ~PlatformData() {
300 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)), 354 if (profiled_thread_ != NULL) {
301 vm_tgid_(getpid()), 355 CloseHandle(profiled_thread_);
356 profiled_thread_ = NULL;
357 }
358 }
359
360 HANDLE profiled_thread() { return profiled_thread_; }
361 ThreadId profiled_thread_id() { return profiled_thread_id_; }
362
363 private:
364 HANDLE profiled_thread_;
365 ThreadId profiled_thread_id_;
366 };
367
368 #endif
369
370
371 class SamplerThread : public Thread {
372 public:
373 static const int kSamplerThreadStackSize = 64 * KB;
374
375 explicit SamplerThread(int interval)
376 : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
302 interval_(interval) {} 377 interval_(interval) {}
303 378
304 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); } 379 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
305 static void TearDown() { delete mutex_; } 380 static void TearDown() { delete mutex_; }
306 381
382 #if defined(USE_SIGNALS)
307 static void InstallSignalHandler() { 383 static void InstallSignalHandler() {
308 struct sigaction sa; 384 struct sigaction sa;
309 sa.sa_sigaction = ProfilerSignalHandler; 385 sa.sa_sigaction = ProfilerSignalHandler;
310 sigemptyset(&sa.sa_mask); 386 sigemptyset(&sa.sa_mask);
311 sa.sa_flags = SA_RESTART | SA_SIGINFO; 387 sa.sa_flags = SA_RESTART | SA_SIGINFO;
312 signal_handler_installed_ = 388 signal_handler_installed_ =
313 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); 389 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
314 } 390 }
315 391
316 static void RestoreSignalHandler() { 392 static void RestoreSignalHandler() {
317 if (signal_handler_installed_) { 393 if (signal_handler_installed_) {
318 sigaction(SIGPROF, &old_signal_handler_, 0); 394 sigaction(SIGPROF, &old_signal_handler_, 0);
319 signal_handler_installed_ = false; 395 signal_handler_installed_ = false;
320 } 396 }
321 } 397 }
398 #endif
322 399
323 static void AddActiveSampler(Sampler* sampler) { 400 static void AddActiveSampler(Sampler* sampler) {
324 ScopedLock lock(mutex_); 401 ScopedLock lock(mutex_);
325 SamplerRegistry::AddActiveSampler(sampler); 402 SamplerRegistry::AddActiveSampler(sampler);
326 if (instance_ == NULL) { 403 if (instance_ == NULL) {
327 // Start a thread that will send SIGPROF signal to VM threads, 404 // Start a thread that will send SIGPROF signal to VM threads,
328 // when CPU profiling will be enabled. 405 // when CPU profiling will be enabled.
329 instance_ = new SignalSender(sampler->interval()); 406 instance_ = new SamplerThread(sampler->interval());
330 instance_->StartSynchronously(); 407 instance_->StartSynchronously();
331 } else { 408 } else {
332 ASSERT(instance_->interval_ == sampler->interval()); 409 ASSERT(instance_->interval_ == sampler->interval());
333 } 410 }
334 } 411 }
335 412
336 static void RemoveActiveSampler(Sampler* sampler) { 413 static void RemoveActiveSampler(Sampler* sampler) {
337 ScopedLock lock(mutex_); 414 ScopedLock lock(mutex_);
338 SamplerRegistry::RemoveActiveSampler(sampler); 415 SamplerRegistry::RemoveActiveSampler(sampler);
339 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 416 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
340 instance_->Join(); 417 instance_->Join();
341 delete instance_; 418 delete instance_;
342 instance_ = NULL; 419 instance_ = NULL;
420 #if defined(USE_SIGNALS)
343 RestoreSignalHandler(); 421 RestoreSignalHandler();
422 #endif
344 } 423 }
345 } 424 }
346 425
347 // Implement Thread::Run(). 426 // Implement Thread::Run().
348 virtual void Run() { 427 virtual void Run() {
349 SamplerRegistry::State state; 428 SamplerRegistry::State state;
350 while ((state = SamplerRegistry::GetState()) != 429 while ((state = SamplerRegistry::GetState()) !=
351 SamplerRegistry::HAS_NO_SAMPLERS) { 430 SamplerRegistry::HAS_NO_SAMPLERS) {
352 // When CPU profiling is enabled both JavaScript and C++ code is 431 // When CPU profiling is enabled both JavaScript and C++ code is
353 // profiled. We must not suspend. 432 // profiled. We must not suspend.
354 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) { 433 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
434 #if defined(USE_SIGNALS)
355 if (!signal_handler_installed_) InstallSignalHandler(); 435 if (!signal_handler_installed_) InstallSignalHandler();
436 #endif
356 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this); 437 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
357 } else { 438 } else {
439 #if defined(USE_SIGNALS)
358 if (signal_handler_installed_) RestoreSignalHandler(); 440 if (signal_handler_installed_) RestoreSignalHandler();
441 #endif
359 } 442 }
360 Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough. 443 Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough.
361 } 444 }
362 } 445 }
363 446
364 static void DoCpuProfile(Sampler* sampler, void* raw_sender) { 447 static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
448 if (!sampler->isolate()->IsInitialized()) return;
365 if (!sampler->IsProfiling()) return; 449 if (!sampler->IsProfiling()) return;
366 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender); 450 SamplerThread* sender = reinterpret_cast<SamplerThread*>(raw_sender);
367 sender->SendProfilingSignal(sampler->platform_data()->vm_tid()); 451 sender->SampleContext(sampler);
368 } 452 }
369 453
370 void SendProfilingSignal(int tid) { 454 #if defined(USE_SIGNALS)
455 void SampleContext(Sampler* sampler) {
371 if (!signal_handler_installed_) return; 456 if (!signal_handler_installed_) return;
457 Sampler::PlatformData* platform_data = sampler->platform_data();
458 int tid = platform_data->vm_tid();
372 // Glibc doesn't provide a wrapper for tgkill(2). 459 // Glibc doesn't provide a wrapper for tgkill(2).
373 #if defined(ANDROID) 460 #if defined(ANDROID)
374 syscall(__NR_tgkill, vm_tgid_, tid, SIGPROF); 461 syscall(__NR_tgkill, platform_data->vm_tgid(), tid, SIGPROF);
375 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ 462 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
376 || defined(__sun) 463 || defined(__sun)
377 pthread_kill(tid, SIGPROF); 464 pthread_kill(tid, SIGPROF);
378 #else 465 #else
379 int result = syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF); 466 int result = syscall(SYS_tgkill, platform_data->vm_tgid(), tid, SIGPROF);
380 USE(result); 467 USE(result);
381 ASSERT(result == 0); 468 ASSERT(result == 0);
382 #endif 469 #endif
383 } 470 }
384 471
385 void Sleep() { 472 void Sleep() {
386 // Convert ms to us and subtract 100 us to compensate delays 473 // Convert ms to us and subtract 100 us to compensate delays
387 // occuring during signal delivery. 474 // occuring during signal delivery.
388 useconds_t interval = interval_ * 1000 - 100; 475 useconds_t interval = interval_ * 1000 - 100;
389 #if defined(ANDROID) 476 #if defined(ANDROID)
390 usleep(interval); 477 usleep(interval);
391 #else 478 #else
392 int result = usleep(interval); 479 int result = usleep(interval);
393 #ifdef DEBUG 480 #ifdef DEBUG
394 if (result != 0 && errno != EINTR) { 481 if (result != 0 && errno != EINTR) {
395 fprintf(stderr, 482 fprintf(stderr,
396 "SignalSender usleep error; interval = %u, errno = %d\n", 483 "SamplerThread usleep error; interval = %u, errno = %d\n",
397 interval, 484 interval,
398 errno); 485 errno);
399 ASSERT(result == 0 || errno == EINTR); 486 ASSERT(result == 0 || errno == EINTR);
400 } 487 }
401 #endif // DEBUG 488 #endif // DEBUG
402 USE(result); 489 USE(result);
403 #endif // ANDROID 490 #endif // ANDROID
404 } 491 }
405 492
406 const int vm_tgid_; 493 #elif defined(__MACH__)
494
495 void SampleContext(Sampler* sampler) {
496 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread();
497 Isolate* isolate = sampler->isolate();
498 #if defined(USE_SIMULATOR)
499 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
500 ThreadId thread_id = sampler->platform_data()->profiled_thread_id();
501 Isolate::PerIsolateThreadData* per_thread_data = isolate->
502 FindPerThreadDataForThread(thread_id);
503 if (!per_thread_data) return;
504 Simulator* sim = per_thread_data->simulator();
505 // Check if there is active simulator before allocating TickSample.
506 if (!sim) return;
507 #endif
508 #endif // USE_SIMULATOR
509 TickSample sample_obj;
510 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
511 if (sample == NULL) sample = &sample_obj;
512
513 if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
514
515 #if V8_HOST_ARCH_X64
516 thread_state_flavor_t flavor = x86_THREAD_STATE64;
517 x86_thread_state64_t state;
518 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
519 #if __DARWIN_UNIX03
520 #define REGISTER_FIELD(name) __r ## name
521 #else
522 #define REGISTER_FIELD(name) r ## name
523 #endif // __DARWIN_UNIX03
524 #elif V8_HOST_ARCH_IA32
525 thread_state_flavor_t flavor = i386_THREAD_STATE;
526 i386_thread_state_t state;
527 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
528 #if __DARWIN_UNIX03
529 #define REGISTER_FIELD(name) __e ## name
530 #else
531 #define REGISTER_FIELD(name) e ## name
532 #endif // __DARWIN_UNIX03
533 #else
534 #error Unsupported Mac OS X host architecture.
535 #endif // V8_HOST_ARCH
536
537 if (thread_get_state(profiled_thread,
538 flavor,
539 reinterpret_cast<natural_t*>(&state),
540 &count) == KERN_SUCCESS) {
541 sample->state = isolate->current_vm_state();
542 #if defined(USE_SIMULATOR)
543 #if V8_TARGET_ARCH_ARM
544 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
545 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
546 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11));
547 #elif V8_TARGET_ARCH_MIPS
548 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
549 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
550 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
551 #endif
552 #else
553 sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
554 sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
555 sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
556 #endif // USE_SIMULATOR
557 #undef REGISTER_FIELD
558 sampler->SampleStack(sample);
559 sampler->Tick(sample);
560 }
561 thread_resume(profiled_thread);
562 }
563
564 void Sleep() {
565 OS::Sleep(interval_);
566 }
567
568 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
569
570 void SampleContext(Sampler* sampler) {
571 HANDLE profiled_thread = sampler->platform_data()->profiled_thread();
572 if (profiled_thread == NULL) return;
573
574 // Context used for sampling the register state of the profiled thread.
575 CONTEXT context;
576 memset(&context, 0, sizeof(context));
577
578 Isolate* isolate = sampler->isolate();
579 #if defined(USE_SIMULATOR)
580 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
581 ThreadId thread_id = sampler->platform_data()->profiled_thread_id();
582 Isolate::PerIsolateThreadData* per_thread_data = isolate->
583 FindPerThreadDataForThread(thread_id);
584 if (!per_thread_data) return;
585 Simulator* sim = per_thread_data->simulator();
586 // Check if there is active simulator before allocating TickSample.
587 if (!sim) return;
588 #endif
589 #endif // USE_SIMULATOR
590 TickSample sample_obj;
591 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
592 if (sample == NULL) sample = &sample_obj;
593
594 static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
595 if (SuspendThread(profiled_thread) == kSuspendFailed) return;
596 sample->state = isolate->current_vm_state();
597
598 context.ContextFlags = CONTEXT_FULL;
599 if (GetThreadContext(profiled_thread, &context) != 0) {
600 #if defined(USE_SIMULATOR)
601 #if V8_TARGET_ARCH_ARM
602 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
603 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
604 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11));
605 #elif V8_TARGET_ARCH_MIPS
606 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
607 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
608 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
609 #endif
610 #else
611 #if V8_HOST_ARCH_X64
612 sample->pc = reinterpret_cast<Address>(context.Rip);
613 sample->sp = reinterpret_cast<Address>(context.Rsp);
614 sample->fp = reinterpret_cast<Address>(context.Rbp);
615 #else
616 sample->pc = reinterpret_cast<Address>(context.Eip);
617 sample->sp = reinterpret_cast<Address>(context.Esp);
618 sample->fp = reinterpret_cast<Address>(context.Ebp);
619 #endif
620 #endif // USE_SIMULATOR
621 sampler->SampleStack(sample);
622 sampler->Tick(sample);
623 }
624 ResumeThread(profiled_thread);
625 }
626
627 void Sleep() {
628 OS::Sleep(interval_);
629 }
630
631 #endif // USE_SIGNALS
632
407 const int interval_; 633 const int interval_;
408 634
409 // Protects the process wide state below. 635 // Protects the process wide state below.
410 static Mutex* mutex_; 636 static Mutex* mutex_;
411 static SignalSender* instance_; 637 static SamplerThread* instance_;
638 #if defined(USE_SIGNALS)
412 static bool signal_handler_installed_; 639 static bool signal_handler_installed_;
413 static struct sigaction old_signal_handler_; 640 static struct sigaction old_signal_handler_;
641 #endif
414 642
415 private: 643 private:
416 DISALLOW_COPY_AND_ASSIGN(SignalSender); 644 DISALLOW_COPY_AND_ASSIGN(SamplerThread);
417 }; 645 };
418 646
419 647
420 Mutex* SignalSender::mutex_ = NULL; 648 Mutex* SamplerThread::mutex_ = NULL;
421 SignalSender* SignalSender::instance_ = NULL; 649 SamplerThread* SamplerThread::instance_ = NULL;
422 struct sigaction SignalSender::old_signal_handler_; 650 #if defined(USE_SIGNALS)
423 bool SignalSender::signal_handler_installed_ = false; 651 struct sigaction SamplerThread::old_signal_handler_;
652 bool SamplerThread::signal_handler_installed_ = false;
653 #endif
424 654
425 655
426 void Sampler::SetUp() { 656 void Sampler::SetUp() {
427 SignalSender::SetUp(); 657 SamplerThread::SetUp();
428 } 658 }
429 659
430 660
431 void Sampler::TearDown() { 661 void Sampler::TearDown() {
432 SignalSender::TearDown(); 662 SamplerThread::TearDown();
433 } 663 }
434 664
435 665
436 Sampler::Sampler(Isolate* isolate, int interval) 666 Sampler::Sampler(Isolate* isolate, int interval)
437 : isolate_(isolate), 667 : isolate_(isolate),
438 interval_(interval), 668 interval_(interval),
439 profiling_(false), 669 profiling_(false),
440 active_(false), 670 active_(false),
441 samples_taken_(0) { 671 samples_taken_(0) {
442 data_ = new PlatformData; 672 data_ = new PlatformData;
443 } 673 }
444 674
445 675
446 Sampler::~Sampler() { 676 Sampler::~Sampler() {
447 ASSERT(!IsActive()); 677 ASSERT(!IsActive());
448 delete data_; 678 delete data_;
449 } 679 }
450 680
451 void Sampler::Start() { 681 void Sampler::Start() {
452 ASSERT(!IsActive()); 682 ASSERT(!IsActive());
453 SetActive(true); 683 SetActive(true);
454 SignalSender::AddActiveSampler(this); 684 SamplerThread::AddActiveSampler(this);
455 } 685 }
456 686
457 687
458 void Sampler::Stop() { 688 void Sampler::Stop() {
459 ASSERT(IsActive()); 689 ASSERT(IsActive());
460 SignalSender::RemoveActiveSampler(this); 690 SamplerThread::RemoveActiveSampler(this);
461 SetActive(false); 691 SetActive(false);
462 } 692 }
463 693
464 #else
465
466 void Sampler::SetUp() {
467 }
468
469
470 void Sampler::TearDown() {
471 }
472
473 #endif // __linux__ || _*BSD__ || __sun
474
475 void Sampler::SampleStack(TickSample* sample) { 694 void Sampler::SampleStack(TickSample* sample) {
476 StackTracer::Trace(isolate_, sample); 695 StackTracer::Trace(isolate_, sample);
477 if (++samples_taken_ < 0) samples_taken_ = 0; 696 if (++samples_taken_ < 0) samples_taken_ = 0;
478 } 697 }
479 698
480 } } // namespace v8::internal 699 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform-win32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698