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

Side by Side Diff: src/profiler/sampler.cc

Issue 1926863003: Make Isolate::GetStackSample API support simulator (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 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
« src/api.cc ('K') | « src/profiler/sampler.h ('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 // 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 4
5 #include "src/profiler/sampler.h" 5 #include "src/profiler/sampler.h"
6 6
7 #if V8_OS_POSIX && !V8_OS_CYGWIN 7 #if V8_OS_POSIX && !V8_OS_CYGWIN
8 8
9 #define USE_SIGNALS 9 #define USE_SIGNALS
10 10
(...skipping 30 matching lines...) Expand all
41 #include "src/base/win32-headers.h" 41 #include "src/base/win32-headers.h"
42 42
43 #endif 43 #endif
44 44
45 #include "src/atomic-utils.h" 45 #include "src/atomic-utils.h"
46 #include "src/base/platform/platform.h" 46 #include "src/base/platform/platform.h"
47 #include "src/flags.h" 47 #include "src/flags.h"
48 #include "src/frames-inl.h" 48 #include "src/frames-inl.h"
49 #include "src/log.h" 49 #include "src/log.h"
50 #include "src/profiler/cpu-profiler-inl.h" 50 #include "src/profiler/cpu-profiler-inl.h"
51 #include "src/simulator.h"
52 #include "src/v8threads.h" 51 #include "src/v8threads.h"
53 #include "src/vm-state-inl.h" 52 #include "src/vm-state-inl.h"
54 53
55 54
56 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) 55 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
57 56
58 // Not all versions of Android's C library provide ucontext_t. 57 // Not all versions of Android's C library provide ucontext_t.
59 // Detect this and provide custom but compatible definitions. Note that these 58 // Detect this and provide custom but compatible definitions. Note that these
60 // follow the GLibc naming convention to access register values from 59 // follow the GLibc naming convention to access register values from
61 // mcontext_t. 60 // mcontext_t.
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 324
326 HANDLE profiled_thread() { return profiled_thread_; } 325 HANDLE profiled_thread() { return profiled_thread_; }
327 326
328 private: 327 private:
329 HANDLE profiled_thread_; 328 HANDLE profiled_thread_;
330 }; 329 };
331 #endif 330 #endif
332 331
333 332
334 #if defined(USE_SIMULATOR) 333 #if defined(USE_SIMULATOR)
335 class SimulatorHelper { 334 bool SimulatorHelper::FillRegisters(Isolate* isolate,
336 public: 335 v8::RegisterState* state) {
337 inline bool Init(Isolate* isolate) { 336 Simulator *simulator = isolate->thread_local_top()->simulator_;
338 simulator_ = isolate->thread_local_top()->simulator_; 337 // Check if there is active simulator.
339 // Check if there is active simulator. 338 if (simulator == NULL) return false;
340 return simulator_ != NULL; 339 #if V8_TARGET_ARCH_ARM
340 if (!simulator->has_bad_pc()) {
alph 2016/04/29 20:59:57 not sure how did it work before. let's just return
lpy 2016/04/29 21:43:10 an uninitialized register state has a pc value 0,
341 state->pc = reinterpret_cast<Address>(simulator->get_pc());
341 } 342 }
342 343 state->sp = reinterpret_cast<Address>(simulator->get_register(
alph 2016/04/29 20:59:57 nit: should fit one line. run git cl format.
lpy 2016/04/29 21:43:10 Done.
343 inline void FillRegisters(v8::RegisterState* state) { 344 Simulator::sp));
344 #if V8_TARGET_ARCH_ARM 345 state->fp = reinterpret_cast<Address>(simulator->get_register(
345 if (!simulator_->has_bad_pc()) { 346 Simulator::r11));
346 state->pc = reinterpret_cast<Address>(simulator_->get_pc());
347 }
348 state->sp = reinterpret_cast<Address>(simulator_->get_register(
349 Simulator::sp));
350 state->fp = reinterpret_cast<Address>(simulator_->get_register(
351 Simulator::r11));
352 #elif V8_TARGET_ARCH_ARM64 347 #elif V8_TARGET_ARCH_ARM64
353 if (simulator_->sp() == 0 || simulator_->fp() == 0) { 348 if (simulator->sp() == 0 || simulator->fp() == 0) {
354 // It's possible that the simulator is interrupted while it is updating 349 // It's possible that the simulator is interrupted while it is updating
355 // the sp or fp register. ARM64 simulator does this in two steps: 350 // the sp or fp register. ARM64 simulator does this in two steps:
356 // first setting it to zero and then setting it to a new value. 351 // first setting it to zero and then setting it to a new value.
357 // Bailout if sp/fp doesn't contain the new value. 352 // Bailout if sp/fp doesn't contain the new value.
358 // 353 //
359 // FIXME: The above doesn't really solve the issue. 354 // FIXME: The above doesn't really solve the issue.
360 // If a 64-bit target is executed on a 32-bit host even the final 355 // If a 64-bit target is executed on a 32-bit host even the final
361 // write is non-atomic, so it might obtain a half of the result. 356 // write is non-atomic, so it might obtain a half of the result.
362 // Moreover as long as the register set code uses memcpy (as of now), 357 // Moreover as long as the register set code uses memcpy (as of now),
363 // it is not guaranteed to be atomic even when both host and target 358 // it is not guaranteed to be atomic even when both host and target
364 // are of same bitness. 359 // are of same bitness.
365 return; 360 return false;
366 } 361 }
367 state->pc = reinterpret_cast<Address>(simulator_->pc()); 362 state->pc = reinterpret_cast<Address>(simulator->pc());
368 state->sp = reinterpret_cast<Address>(simulator_->sp()); 363 state->sp = reinterpret_cast<Address>(simulator->sp());
369 state->fp = reinterpret_cast<Address>(simulator_->fp()); 364 state->fp = reinterpret_cast<Address>(simulator->fp());
370 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 365 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
371 if (!simulator_->has_bad_pc()) { 366 if (!simulator->has_bad_pc()) {
372 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 367 state->pc = reinterpret_cast<Address>(simulator->get_pc());
373 } 368 }
374 state->sp = reinterpret_cast<Address>(simulator_->get_register( 369 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
375 Simulator::sp)); 370 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
376 state->fp = reinterpret_cast<Address>(simulator_->get_register(
377 Simulator::fp));
378 #elif V8_TARGET_ARCH_PPC 371 #elif V8_TARGET_ARCH_PPC
379 if (!simulator_->has_bad_pc()) { 372 if (!simulator->has_bad_pc()) {
380 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 373 state->pc = reinterpret_cast<Address>(simulator->get_pc());
381 } 374 }
382 state->sp = 375 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
383 reinterpret_cast<Address>(simulator_->get_register(Simulator::sp)); 376 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
384 state->fp =
385 reinterpret_cast<Address>(simulator_->get_register(Simulator::fp));
386 #elif V8_TARGET_ARCH_S390 377 #elif V8_TARGET_ARCH_S390
387 if (!simulator_->has_bad_pc()) { 378 if (!simulator->has_bad_pc()) {
388 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 379 state->pc = reinterpret_cast<Address>(simulator->get_pc());
389 } 380 }
390 state->sp = 381 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
391 reinterpret_cast<Address>(simulator_->get_register(Simulator::sp)); 382 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
392 state->fp =
393 reinterpret_cast<Address>(simulator_->get_register(Simulator::fp));
394 #endif 383 #endif
395 } 384 // It possible that the simulator is interrupted while it is updating
396 385 // the sp or fp register. ARM64 simulator does this in two steps:
397 private: 386 // first setting it to zero and then setting it to the new value.
398 Simulator* simulator_; 387 // Bailout if sp/fp doesn't contain the new value.
399 }; 388 if (state->sp == 0 || state->fp == 0) return false;
alph 2016/04/29 20:59:57 this seems to be already done at line 348. We prob
lpy 2016/04/29 21:43:11 Yes, line 348 is for ARM64 only, let's delete the
389 return true;
390 }
400 #endif // USE_SIMULATOR 391 #endif // USE_SIMULATOR
401 392
402 393
403 #if defined(USE_SIGNALS) 394 #if defined(USE_SIGNALS)
404 395
405 class SignalHandler : public AllStatic { 396 class SignalHandler : public AllStatic {
406 public: 397 public:
407 static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); } 398 static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); }
408 static void TearDown() { delete mutex_; mutex_ = NULL; } 399 static void TearDown() { delete mutex_; mutex_ = NULL; }
409 400
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 if (isolate == NULL || !isolate->IsInUse()) return; 471 if (isolate == NULL || !isolate->IsInUse()) return;
481 472
482 if (v8::Locker::IsActive() && 473 if (v8::Locker::IsActive() &&
483 !isolate->thread_manager()->IsLockedByCurrentThread()) { 474 !isolate->thread_manager()->IsLockedByCurrentThread()) {
484 return; 475 return;
485 } 476 }
486 477
487 v8::RegisterState state; 478 v8::RegisterState state;
488 479
489 #if defined(USE_SIMULATOR) 480 #if defined(USE_SIMULATOR)
490 SimulatorHelper helper; 481 if (!SimulatorHelper::FillRegisters(isolate, &state)) return;
491 if (!helper.Init(isolate)) return;
492 helper.FillRegisters(&state);
493 // It possible that the simulator is interrupted while it is updating
494 // the sp or fp register. ARM64 simulator does this in two steps:
495 // first setting it to zero and then setting it to the new value.
496 // Bailout if sp/fp doesn't contain the new value.
497 if (state.sp == 0 || state.fp == 0) return;
498 #else 482 #else
499 // Extracting the sample from the context is extremely machine dependent. 483 // Extracting the sample from the context is extremely machine dependent.
500 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 484 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
501 #if !(V8_OS_OPENBSD || (V8_OS_LINUX && (V8_HOST_ARCH_PPC || V8_HOST_ARCH_S390))) 485 #if !(V8_OS_OPENBSD || (V8_OS_LINUX && (V8_HOST_ARCH_PPC || V8_HOST_ARCH_S390)))
502 mcontext_t& mcontext = ucontext->uc_mcontext; 486 mcontext_t& mcontext = ucontext->uc_mcontext;
503 #endif 487 #endif
504 #if V8_OS_LINUX 488 #if V8_OS_LINUX
505 #if V8_HOST_ARCH_IA32 489 #if V8_HOST_ARCH_IA32
506 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); 490 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
507 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); 491 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 } 1000 }
1017 pthread_kill(platform_data()->vm_tid(), SIGPROF); 1001 pthread_kill(platform_data()->vm_tid(), SIGPROF);
1018 } 1002 }
1019 1003
1020 #elif V8_OS_WIN || V8_OS_CYGWIN 1004 #elif V8_OS_WIN || V8_OS_CYGWIN
1021 1005
1022 void Sampler::DoSample() { 1006 void Sampler::DoSample() {
1023 HANDLE profiled_thread = platform_data()->profiled_thread(); 1007 HANDLE profiled_thread = platform_data()->profiled_thread();
1024 if (profiled_thread == NULL) return; 1008 if (profiled_thread == NULL) return;
1025 1009
1026 #if defined(USE_SIMULATOR)
1027 SimulatorHelper helper;
1028 if (!helper.Init(isolate())) return;
1029 #endif
1030
1031 const DWORD kSuspendFailed = static_cast<DWORD>(-1); 1010 const DWORD kSuspendFailed = static_cast<DWORD>(-1);
1032 if (SuspendThread(profiled_thread) == kSuspendFailed) return; 1011 if (SuspendThread(profiled_thread) == kSuspendFailed) return;
1033 1012
1034 // Context used for sampling the register state of the profiled thread. 1013 // Context used for sampling the register state of the profiled thread.
1035 CONTEXT context; 1014 CONTEXT context;
1036 memset(&context, 0, sizeof(context)); 1015 memset(&context, 0, sizeof(context));
1037 context.ContextFlags = CONTEXT_FULL; 1016 context.ContextFlags = CONTEXT_FULL;
1038 if (GetThreadContext(profiled_thread, &context) != 0) { 1017 if (GetThreadContext(profiled_thread, &context) != 0) {
1039 v8::RegisterState state; 1018 v8::RegisterState state;
1040 #if defined(USE_SIMULATOR) 1019 #if defined(USE_SIMULATOR)
1041 helper.FillRegisters(&state); 1020 if (!SimulatorHelper::FillRegisters(isolate(), &state)) return;
alph 2016/04/29 20:59:57 you cannot return without resuming the thread.
lpy 2016/04/29 21:43:10 Done.
1042 #else 1021 #else
1043 #if V8_HOST_ARCH_X64 1022 #if V8_HOST_ARCH_X64
1044 state.pc = reinterpret_cast<Address>(context.Rip); 1023 state.pc = reinterpret_cast<Address>(context.Rip);
1045 state.sp = reinterpret_cast<Address>(context.Rsp); 1024 state.sp = reinterpret_cast<Address>(context.Rsp);
1046 state.fp = reinterpret_cast<Address>(context.Rbp); 1025 state.fp = reinterpret_cast<Address>(context.Rbp);
1047 #else 1026 #else
1048 state.pc = reinterpret_cast<Address>(context.Eip); 1027 state.pc = reinterpret_cast<Address>(context.Eip);
1049 state.sp = reinterpret_cast<Address>(context.Esp); 1028 state.sp = reinterpret_cast<Address>(context.Esp);
1050 state.fp = reinterpret_cast<Address>(context.Ebp); 1029 state.fp = reinterpret_cast<Address>(context.Ebp);
1051 #endif 1030 #endif
1052 #endif // USE_SIMULATOR 1031 #endif // USE_SIMULATOR
1053 SampleStack(state); 1032 SampleStack(state);
1054 } 1033 }
1055 ResumeThread(profiled_thread); 1034 ResumeThread(profiled_thread);
1056 } 1035 }
1057 1036
1058 #endif // USE_SIGNALS 1037 #endif // USE_SIGNALS
1059 1038
1060 1039
1061 } // namespace internal 1040 } // namespace internal
1062 } // namespace v8 1041 } // namespace v8
OLDNEW
« src/api.cc ('K') | « src/profiler/sampler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698