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

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/profiler/sampler.h ('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()) {
341 state->pc = reinterpret_cast<Address>(simulator->get_pc());
341 } 342 }
342 343 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
343 inline void FillRegisters(v8::RegisterState* state) { 344 state->fp = reinterpret_cast<Address>(simulator->get_register(
344 #if V8_TARGET_ARCH_ARM 345 Simulator::r11));
345 if (!simulator_->has_bad_pc()) {
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 346 #elif V8_TARGET_ARCH_ARM64
353 if (simulator_->sp() == 0 || simulator_->fp() == 0) { 347 state->pc = reinterpret_cast<Address>(simulator->pc());
354 // It's possible that the simulator is interrupted while it is updating 348 state->sp = reinterpret_cast<Address>(simulator->sp());
355 // the sp or fp register. ARM64 simulator does this in two steps: 349 state->fp = reinterpret_cast<Address>(simulator->fp());
356 // first setting it to zero and then setting it to a new value.
357 // Bailout if sp/fp doesn't contain the new value.
358 //
359 // 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
361 // 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),
363 // it is not guaranteed to be atomic even when both host and target
364 // are of same bitness.
365 return;
366 }
367 state->pc = reinterpret_cast<Address>(simulator_->pc());
368 state->sp = reinterpret_cast<Address>(simulator_->sp());
369 state->fp = reinterpret_cast<Address>(simulator_->fp());
370 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 350 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
371 if (!simulator_->has_bad_pc()) { 351 if (!simulator->has_bad_pc()) {
372 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 352 state->pc = reinterpret_cast<Address>(simulator->get_pc());
373 } 353 }
374 state->sp = reinterpret_cast<Address>(simulator_->get_register( 354 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
375 Simulator::sp)); 355 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 356 #elif V8_TARGET_ARCH_PPC
379 if (!simulator_->has_bad_pc()) { 357 if (!simulator->has_bad_pc()) {
380 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 358 state->pc = reinterpret_cast<Address>(simulator->get_pc());
381 } 359 }
382 state->sp = 360 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
383 reinterpret_cast<Address>(simulator_->get_register(Simulator::sp)); 361 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 362 #elif V8_TARGET_ARCH_S390
387 if (!simulator_->has_bad_pc()) { 363 if (!simulator->has_bad_pc()) {
388 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 364 state->pc = reinterpret_cast<Address>(simulator->get_pc());
389 } 365 }
390 state->sp = 366 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
391 reinterpret_cast<Address>(simulator_->get_register(Simulator::sp)); 367 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
392 state->fp =
393 reinterpret_cast<Address>(simulator_->get_register(Simulator::fp));
394 #endif 368 #endif
369 if (state->sp == 0 || state->fp == 0) {
370 // It possible that the simulator is interrupted while it is updating
371 // the sp or fp register. ARM64 simulator does this in two steps:
372 // first setting it to zero and then setting it to the new value.
373 // Bailout if sp/fp doesn't contain the new value.
374 //
375 // FIXME: The above doesn't really solve the issue.
376 // If a 64-bit target is executed on a 32-bit host even the final
377 // write is non-atomic, so it might obtain a half of the result.
378 // Moreover as long as the register set code uses memcpy (as of now),
379 // it is not guaranteed to be atomic even when both host and target
380 // are of same bitness.
381 return false;
395 } 382 }
396 383 return true;
397 private: 384 }
398 Simulator* simulator_;
399 };
400 #endif // USE_SIMULATOR 385 #endif // USE_SIMULATOR
401 386
402 387
403 #if defined(USE_SIGNALS) 388 #if defined(USE_SIGNALS)
404 389
405 class SignalHandler : public AllStatic { 390 class SignalHandler : public AllStatic {
406 public: 391 public:
407 static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); } 392 static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); }
408 static void TearDown() { delete mutex_; mutex_ = NULL; } 393 static void TearDown() { delete mutex_; mutex_ = NULL; }
409 394
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 if (isolate == NULL || !isolate->IsInUse()) return; 465 if (isolate == NULL || !isolate->IsInUse()) return;
481 466
482 if (v8::Locker::IsActive() && 467 if (v8::Locker::IsActive() &&
483 !isolate->thread_manager()->IsLockedByCurrentThread()) { 468 !isolate->thread_manager()->IsLockedByCurrentThread()) {
484 return; 469 return;
485 } 470 }
486 471
487 v8::RegisterState state; 472 v8::RegisterState state;
488 473
489 #if defined(USE_SIMULATOR) 474 #if defined(USE_SIMULATOR)
490 SimulatorHelper helper; 475 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 476 #else
499 // Extracting the sample from the context is extremely machine dependent. 477 // Extracting the sample from the context is extremely machine dependent.
500 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 478 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
501 #if !(V8_OS_OPENBSD || (V8_OS_LINUX && (V8_HOST_ARCH_PPC || V8_HOST_ARCH_S390))) 479 #if !(V8_OS_OPENBSD || (V8_OS_LINUX && (V8_HOST_ARCH_PPC || V8_HOST_ARCH_S390)))
502 mcontext_t& mcontext = ucontext->uc_mcontext; 480 mcontext_t& mcontext = ucontext->uc_mcontext;
503 #endif 481 #endif
504 #if V8_OS_LINUX 482 #if V8_OS_LINUX
505 #if V8_HOST_ARCH_IA32 483 #if V8_HOST_ARCH_IA32
506 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); 484 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
507 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); 485 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 } 994 }
1017 pthread_kill(platform_data()->vm_tid(), SIGPROF); 995 pthread_kill(platform_data()->vm_tid(), SIGPROF);
1018 } 996 }
1019 997
1020 #elif V8_OS_WIN || V8_OS_CYGWIN 998 #elif V8_OS_WIN || V8_OS_CYGWIN
1021 999
1022 void Sampler::DoSample() { 1000 void Sampler::DoSample() {
1023 HANDLE profiled_thread = platform_data()->profiled_thread(); 1001 HANDLE profiled_thread = platform_data()->profiled_thread();
1024 if (profiled_thread == NULL) return; 1002 if (profiled_thread == NULL) return;
1025 1003
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); 1004 const DWORD kSuspendFailed = static_cast<DWORD>(-1);
1032 if (SuspendThread(profiled_thread) == kSuspendFailed) return; 1005 if (SuspendThread(profiled_thread) == kSuspendFailed) return;
1033 1006
1034 // Context used for sampling the register state of the profiled thread. 1007 // Context used for sampling the register state of the profiled thread.
1035 CONTEXT context; 1008 CONTEXT context;
1036 memset(&context, 0, sizeof(context)); 1009 memset(&context, 0, sizeof(context));
1037 context.ContextFlags = CONTEXT_FULL; 1010 context.ContextFlags = CONTEXT_FULL;
1038 if (GetThreadContext(profiled_thread, &context) != 0) { 1011 if (GetThreadContext(profiled_thread, &context) != 0) {
1039 v8::RegisterState state; 1012 v8::RegisterState state;
1040 #if defined(USE_SIMULATOR) 1013 #if defined(USE_SIMULATOR)
1041 helper.FillRegisters(&state); 1014 if (!SimulatorHelper::FillRegisters(isolate(), &state)) {
1015 ResumeThread(profiled_thread);
1016 return;
1017 }
1042 #else 1018 #else
1043 #if V8_HOST_ARCH_X64 1019 #if V8_HOST_ARCH_X64
1044 state.pc = reinterpret_cast<Address>(context.Rip); 1020 state.pc = reinterpret_cast<Address>(context.Rip);
1045 state.sp = reinterpret_cast<Address>(context.Rsp); 1021 state.sp = reinterpret_cast<Address>(context.Rsp);
1046 state.fp = reinterpret_cast<Address>(context.Rbp); 1022 state.fp = reinterpret_cast<Address>(context.Rbp);
1047 #else 1023 #else
1048 state.pc = reinterpret_cast<Address>(context.Eip); 1024 state.pc = reinterpret_cast<Address>(context.Eip);
1049 state.sp = reinterpret_cast<Address>(context.Esp); 1025 state.sp = reinterpret_cast<Address>(context.Esp);
1050 state.fp = reinterpret_cast<Address>(context.Ebp); 1026 state.fp = reinterpret_cast<Address>(context.Ebp);
1051 #endif 1027 #endif
1052 #endif // USE_SIMULATOR 1028 #endif // USE_SIMULATOR
1053 SampleStack(state); 1029 SampleStack(state);
1054 } 1030 }
1055 ResumeThread(profiled_thread); 1031 ResumeThread(profiled_thread);
1056 } 1032 }
1057 1033
1058 #endif // USE_SIGNALS 1034 #endif // USE_SIGNALS
1059 1035
1060 1036
1061 } // namespace internal 1037 } // namespace internal
1062 } // namespace v8 1038 } // namespace v8
OLDNEW
« src/profiler/sampler.h ('K') | « src/profiler/sampler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698