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

Side by Side Diff: src/sampler.cc

Issue 15957005: Extract common sampling code into SampleHelper (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 6 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 | « no previous file | 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
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 } ucontext_t; 138 } ucontext_t;
139 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 }; 139 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
140 #endif 140 #endif
141 141
142 #endif // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T) 142 #endif // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T)
143 143
144 144
145 namespace v8 { 145 namespace v8 {
146 namespace internal { 146 namespace internal {
147 147
148 namespace {
149
150 class PlatformDataCommon : public Malloced {
151 public:
152 PlatformDataCommon() : profiled_thread_id_(ThreadId::Current()) {}
153 ThreadId profiled_thread_id() { return profiled_thread_id_; }
154
155 protected:
156 ~PlatformDataCommon() {}
157
158 private:
159 ThreadId profiled_thread_id_;
160 };
161
162 } // namespace
163
148 #if defined(USE_SIGNALS) 164 #if defined(USE_SIGNALS)
149 165
150 class Sampler::PlatformData : public Malloced { 166 class Sampler::PlatformData : public PlatformDataCommon {
151 public: 167 public:
152 PlatformData() 168 PlatformData() : vm_tid_(pthread_self()) {}
153 : vm_tid_(pthread_self()),
154 profiled_thread_id_(ThreadId::Current()) {}
155
156 pthread_t vm_tid() const { return vm_tid_; } 169 pthread_t vm_tid() const { return vm_tid_; }
157 ThreadId profiled_thread_id() { return profiled_thread_id_; }
158 170
159 private: 171 private:
160 pthread_t vm_tid_; 172 pthread_t vm_tid_;
161 ThreadId profiled_thread_id_;
162 }; 173 };
163 174
175 #elif defined(__MACH__)
176
177 class Sampler::PlatformData : public PlatformDataCommon {
178 public:
179 PlatformData() : profiled_thread_(mach_thread_self()) {}
180
181 ~PlatformData() {
182 // Deallocate Mach port for thread.
183 mach_port_deallocate(mach_task_self(), profiled_thread_);
184 }
185
186 thread_act_t profiled_thread() { return profiled_thread_; }
187
188 private:
189 // Note: for profiled_thread_ Mach primitives are used instead of PThread's
190 // because the latter doesn't provide thread manipulation primitives required.
191 // For details, consult "Mac OS X Internals" book, Section 7.3.
192 thread_act_t profiled_thread_;
193 };
194
195 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
196
197 // ----------------------------------------------------------------------------
198 // Win32 profiler support. On Cygwin we use the same sampler implementation as
199 // on Win32.
200
201 class Sampler::PlatformData : public PlatformDataCommon {
202 public:
203 // Get a handle to the calling thread. This is the thread that we are
204 // going to profile. We need to make a copy of the handle because we are
205 // going to use it in the sampler thread. Using GetThreadHandle() will
206 // not work in this case. We're using OpenThread because DuplicateHandle
207 // for some reason doesn't work in Chrome's sandbox.
208 PlatformData()
209 : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
210 THREAD_SUSPEND_RESUME |
211 THREAD_QUERY_INFORMATION,
212 false,
213 GetCurrentThreadId())) {}
214
215 ~PlatformData() {
216 if (profiled_thread_ != NULL) {
217 CloseHandle(profiled_thread_);
218 profiled_thread_ = NULL;
219 }
220 }
221
222 HANDLE profiled_thread() { return profiled_thread_; }
223
224 private:
225 HANDLE profiled_thread_;
226 };
227 #endif
228
229
230 class SampleHelper {
231 public:
232 inline TickSample* Init(Sampler* sampler, Isolate* isolate) {
233 #if defined(USE_SIMULATOR)
234 ThreadId thread_id = sampler->platform_data()->profiled_thread_id();
235 Isolate::PerIsolateThreadData* per_thread_data = isolate->
236 FindPerThreadDataForThread(thread_id);
237 if (!per_thread_data) return NULL;
238 simulator_ = per_thread_data->simulator();
239 // Check if there is active simulator before allocating TickSample.
240 if (!simulator_) return NULL;
241 #endif // USE_SIMULATOR
242 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
243 if (sample == NULL) sample = &sample_obj;
244 return sample;
245 }
246
247 #if defined(USE_SIMULATOR)
248 inline void FillRegisters(TickSample* sample) {
249 sample->pc = reinterpret_cast<Address>(simulator_->get_pc());
250 sample->sp = reinterpret_cast<Address>(simulator_->get_register(
251 Simulator::sp));
252 #if V8_TARGET_ARCH_ARM
253 sample->fp = reinterpret_cast<Address>(simulator_->get_register(
254 Simulator::r11));
255 #elif V8_TARGET_ARCH_MIPS
256 sample->fp = reinterpret_cast<Address>(simulator_->get_register(
257 Simulator::fp));
258 #endif
259 }
260 #endif // USE_SIMULATOR
261
262 private:
263 #if defined(USE_SIMULATOR)
264 Simulator* simulator_;
265 #endif
266 TickSample sample_obj;
267 };
268
269
270 #if defined(USE_SIGNALS)
164 271
165 class SignalHandler : public AllStatic { 272 class SignalHandler : public AllStatic {
166 public: 273 public:
167 static inline void EnsureInstalled() { 274 static inline void EnsureInstalled() {
168 if (signal_handler_installed_) return; 275 if (signal_handler_installed_) return;
169 struct sigaction sa; 276 struct sigaction sa;
170 sa.sa_sigaction = &HandleProfilerSignal; 277 sa.sa_sigaction = &HandleProfilerSignal;
171 sigemptyset(&sa.sa_mask); 278 sigemptyset(&sa.sa_mask);
172 sa.sa_flags = SA_RESTART | SA_SIGINFO; 279 sa.sa_flags = SA_RESTART | SA_SIGINFO;
173 signal_handler_installed_ = 280 signal_handler_installed_ =
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 return; 317 return;
211 } 318 }
212 if (v8::Locker::IsActive() && 319 if (v8::Locker::IsActive() &&
213 !isolate->thread_manager()->IsLockedByCurrentThread()) { 320 !isolate->thread_manager()->IsLockedByCurrentThread()) {
214 return; 321 return;
215 } 322 }
216 323
217 Sampler* sampler = isolate->logger()->sampler(); 324 Sampler* sampler = isolate->logger()->sampler();
218 if (sampler == NULL || !sampler->IsActive()) return; 325 if (sampler == NULL || !sampler->IsActive()) return;
219 326
220 #if defined(USE_SIMULATOR) 327 SampleHelper helper;
221 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS 328 TickSample* sample = helper.Init(sampler, isolate);
222 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); 329 if (sample == NULL) return;
223 Isolate::PerIsolateThreadData* per_thread_data = isolate->
224 FindPerThreadDataForThread(thread_id);
225 if (!per_thread_data) return;
226 Simulator* sim = per_thread_data->simulator();
227 // Check if there is active simulator before allocating TickSample.
228 if (!sim) return;
229 #endif
230 #endif // USE_SIMULATOR
231
232 TickSample sample_obj;
233 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
234 if (sample == NULL) sample = &sample_obj;
235 330
236 #if defined(USE_SIMULATOR) 331 #if defined(USE_SIMULATOR)
237 sample->pc = reinterpret_cast<Address>(sim->get_pc()); 332 helper.FillRegisters(sample);
238 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
239 #if V8_TARGET_ARCH_ARM
240 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11));
241 #elif V8_TARGET_ARCH_MIPS
242 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
243 #endif // V8_TARGET_ARCH_*
244 #else 333 #else
245 // Extracting the sample from the context is extremely machine dependent. 334 // Extracting the sample from the context is extremely machine dependent.
246 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 335 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
247 mcontext_t& mcontext = ucontext->uc_mcontext; 336 mcontext_t& mcontext = ucontext->uc_mcontext;
248 sample->state = isolate->current_vm_state(); 337 sample->state = isolate->current_vm_state();
249 #if defined(__linux__) || defined(__ANDROID__) 338 #if defined(__linux__) || defined(__ANDROID__)
250 #if V8_HOST_ARCH_IA32 339 #if V8_HOST_ARCH_IA32
251 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); 340 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
252 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); 341 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
253 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); 342 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); 403 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
315 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); 404 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
316 #endif // __sun 405 #endif // __sun
317 #endif // USE_SIMULATOR 406 #endif // USE_SIMULATOR
318 407
319 sampler->SampleStack(sample); 408 sampler->SampleStack(sample);
320 sampler->Tick(sample); 409 sampler->Tick(sample);
321 #endif // __native_client__ 410 #endif // __native_client__
322 } 411 }
323 412
324 #elif defined(__MACH__)
325 class Sampler::PlatformData : public Malloced {
326 public:
327 PlatformData()
328 : profiled_thread_(mach_thread_self()),
329 profiled_thread_id_(ThreadId::Current()) {}
330
331 ~PlatformData() {
332 // Deallocate Mach port for thread.
333 mach_port_deallocate(mach_task_self(), profiled_thread_);
334 }
335
336 thread_act_t profiled_thread() { return profiled_thread_; }
337 ThreadId profiled_thread_id() { return profiled_thread_id_; }
338
339 private:
340 // Note: for profiled_thread_ Mach primitives are used instead of PThread's
341 // because the latter doesn't provide thread manipulation primitives required.
342 // For details, consult "Mac OS X Internals" book, Section 7.3.
343 thread_act_t profiled_thread_;
344 ThreadId profiled_thread_id_;
345 };
346
347 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
348
349 // ----------------------------------------------------------------------------
350 // Win32 profiler support. On Cygwin we use the same sampler implementation as
351 // on Win32.
352
353 class Sampler::PlatformData : public Malloced {
354 public:
355 // Get a handle to the calling thread. This is the thread that we are
356 // going to profile. We need to make a copy of the handle because we are
357 // going to use it in the sampler thread. Using GetThreadHandle() will
358 // not work in this case. We're using OpenThread because DuplicateHandle
359 // for some reason doesn't work in Chrome's sandbox.
360 PlatformData()
361 : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
362 THREAD_SUSPEND_RESUME |
363 THREAD_QUERY_INFORMATION,
364 false,
365 GetCurrentThreadId())),
366 profiled_thread_id_(ThreadId::Current()) {}
367
368 ~PlatformData() {
369 if (profiled_thread_ != NULL) {
370 CloseHandle(profiled_thread_);
371 profiled_thread_ = NULL;
372 }
373 }
374
375 HANDLE profiled_thread() { return profiled_thread_; }
376 ThreadId profiled_thread_id() { return profiled_thread_id_; }
377
378 private:
379 HANDLE profiled_thread_;
380 ThreadId profiled_thread_id_;
381 };
382
383 #endif 413 #endif
384 414
385 415
386 class SamplerThread : public Thread { 416 class SamplerThread : public Thread {
387 public: 417 public:
388 static const int kSamplerThreadStackSize = 64 * KB; 418 static const int kSamplerThreadStackSize = 64 * KB;
389 419
390 explicit SamplerThread(int interval) 420 explicit SamplerThread(int interval)
391 : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), 421 : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
392 interval_(interval) {} 422 interval_(interval) {}
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 int result = pthread_kill(tid, SIGPROF); 499 int result = pthread_kill(tid, SIGPROF);
470 USE(result); 500 USE(result);
471 ASSERT(result == 0); 501 ASSERT(result == 0);
472 } 502 }
473 503
474 #elif defined(__MACH__) 504 #elif defined(__MACH__)
475 505
476 void SampleContext(Sampler* sampler) { 506 void SampleContext(Sampler* sampler) {
477 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); 507 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread();
478 Isolate* isolate = sampler->isolate(); 508 Isolate* isolate = sampler->isolate();
479 #if defined(USE_SIMULATOR) 509
480 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS 510 SampleHelper helper;
481 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); 511 TickSample* sample = helper.Init(sampler, isolate);
482 Isolate::PerIsolateThreadData* per_thread_data = isolate-> 512 if (sample == NULL) return;
483 FindPerThreadDataForThread(thread_id);
484 if (!per_thread_data) return;
485 Simulator* sim = per_thread_data->simulator();
486 // Check if there is active simulator before allocating TickSample.
487 if (!sim) return;
488 #endif
489 #endif // USE_SIMULATOR
490 TickSample sample_obj;
491 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
492 if (sample == NULL) sample = &sample_obj;
493 513
494 if (KERN_SUCCESS != thread_suspend(profiled_thread)) return; 514 if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
495 515
496 #if V8_HOST_ARCH_X64 516 #if V8_HOST_ARCH_X64
497 thread_state_flavor_t flavor = x86_THREAD_STATE64; 517 thread_state_flavor_t flavor = x86_THREAD_STATE64;
498 x86_thread_state64_t state; 518 x86_thread_state64_t state;
499 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; 519 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
500 #if __DARWIN_UNIX03 520 #if __DARWIN_UNIX03
501 #define REGISTER_FIELD(name) __r ## name 521 #define REGISTER_FIELD(name) __r ## name
502 #else 522 #else
(...skipping 11 matching lines...) Expand all
514 #else 534 #else
515 #error Unsupported Mac OS X host architecture. 535 #error Unsupported Mac OS X host architecture.
516 #endif // V8_HOST_ARCH 536 #endif // V8_HOST_ARCH
517 537
518 if (thread_get_state(profiled_thread, 538 if (thread_get_state(profiled_thread,
519 flavor, 539 flavor,
520 reinterpret_cast<natural_t*>(&state), 540 reinterpret_cast<natural_t*>(&state),
521 &count) == KERN_SUCCESS) { 541 &count) == KERN_SUCCESS) {
522 sample->state = isolate->current_vm_state(); 542 sample->state = isolate->current_vm_state();
523 #if defined(USE_SIMULATOR) 543 #if defined(USE_SIMULATOR)
524 sample->pc = reinterpret_cast<Address>(sim->get_pc()); 544 helper.FillRegisters(sample);
525 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
526 #if V8_TARGET_ARCH_ARM
527 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11));
528 #elif V8_TARGET_ARCH_MIPS
529 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
530 #endif
531 #else 545 #else
532 sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip)); 546 sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
533 sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); 547 sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
534 sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); 548 sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
535 #endif // USE_SIMULATOR 549 #endif // USE_SIMULATOR
536 #undef REGISTER_FIELD 550 #undef REGISTER_FIELD
537 sampler->SampleStack(sample); 551 sampler->SampleStack(sample);
538 sampler->Tick(sample); 552 sampler->Tick(sample);
539 } 553 }
540 thread_resume(profiled_thread); 554 thread_resume(profiled_thread);
541 } 555 }
542 556
543 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) 557 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
544 558
545 void SampleContext(Sampler* sampler) { 559 void SampleContext(Sampler* sampler) {
546 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); 560 HANDLE profiled_thread = sampler->platform_data()->profiled_thread();
547 if (profiled_thread == NULL) return; 561 if (profiled_thread == NULL) return;
548 562
563 Isolate* isolate = sampler->isolate();
564 SampleHelper helper;
565 TickSample* sample = helper.Init(sampler, isolate);
566 if (sample == NULL) return;
567
568 const DWORD kSuspendFailed = static_cast<DWORD>(-1);
569 if (SuspendThread(profiled_thread) == kSuspendFailed) return;
570 sample->state = isolate->current_vm_state();
571
549 // Context used for sampling the register state of the profiled thread. 572 // Context used for sampling the register state of the profiled thread.
550 CONTEXT context; 573 CONTEXT context;
551 memset(&context, 0, sizeof(context)); 574 memset(&context, 0, sizeof(context));
552
553 Isolate* isolate = sampler->isolate();
554 #if defined(USE_SIMULATOR)
555 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
556 ThreadId thread_id = sampler->platform_data()->profiled_thread_id();
557 Isolate::PerIsolateThreadData* per_thread_data = isolate->
558 FindPerThreadDataForThread(thread_id);
559 if (!per_thread_data) return;
560 Simulator* sim = per_thread_data->simulator();
561 // Check if there is active simulator before allocating TickSample.
562 if (!sim) return;
563 #endif
564 #endif // USE_SIMULATOR
565 TickSample sample_obj;
566 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
567 if (sample == NULL) sample = &sample_obj;
568
569 static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
570 if (SuspendThread(profiled_thread) == kSuspendFailed) return;
571 sample->state = isolate->current_vm_state();
572
573 context.ContextFlags = CONTEXT_FULL; 575 context.ContextFlags = CONTEXT_FULL;
574 if (GetThreadContext(profiled_thread, &context) != 0) { 576 if (GetThreadContext(profiled_thread, &context) != 0) {
575 #if defined(USE_SIMULATOR) 577 #if defined(USE_SIMULATOR)
576 sample->pc = reinterpret_cast<Address>(sim->get_pc()); 578 helper.FillRegisters(sample);
577 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
578 #if V8_TARGET_ARCH_ARM
579 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11));
580 #elif V8_TARGET_ARCH_MIPS
581 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
582 #endif
583 #else 579 #else
584 #if V8_HOST_ARCH_X64 580 #if V8_HOST_ARCH_X64
585 sample->pc = reinterpret_cast<Address>(context.Rip); 581 sample->pc = reinterpret_cast<Address>(context.Rip);
586 sample->sp = reinterpret_cast<Address>(context.Rsp); 582 sample->sp = reinterpret_cast<Address>(context.Rsp);
587 sample->fp = reinterpret_cast<Address>(context.Rbp); 583 sample->fp = reinterpret_cast<Address>(context.Rbp);
588 #else 584 #else
589 sample->pc = reinterpret_cast<Address>(context.Eip); 585 sample->pc = reinterpret_cast<Address>(context.Eip);
590 sample->sp = reinterpret_cast<Address>(context.Esp); 586 sample->sp = reinterpret_cast<Address>(context.Esp);
591 sample->fp = reinterpret_cast<Address>(context.Ebp); 587 sample->fp = reinterpret_cast<Address>(context.Ebp);
592 #endif 588 #endif
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 SamplerThread::RemoveActiveSampler(this); 685 SamplerThread::RemoveActiveSampler(this);
690 SetActive(false); 686 SetActive(false);
691 } 687 }
692 688
693 void Sampler::SampleStack(TickSample* sample) { 689 void Sampler::SampleStack(TickSample* sample) {
694 sample->Trace(isolate_); 690 sample->Trace(isolate_);
695 if (++samples_taken_ < 0) samples_taken_ = 0; 691 if (++samples_taken_ < 0) samples_taken_ = 0;
696 } 692 }
697 693
698 } } // namespace v8::internal 694 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698