| Index: src/profiler/tick-sample.cc
|
| diff --git a/src/profiler/tick-sample.cc b/src/profiler/tick-sample.cc
|
| index 8b7fe2c73ac6aceb20a324925a1331042a0f727b..fb5cdbff78eeaec5362b69f764db53380a87c49c 100644
|
| --- a/src/profiler/tick-sample.cc
|
| +++ b/src/profiler/tick-sample.cc
|
| @@ -11,7 +11,6 @@
|
| #include "src/vm-state-inl.h"
|
|
|
| namespace v8 {
|
| -
|
| namespace {
|
|
|
| bool IsSamePage(i::byte* ptr1, i::byte* ptr2) {
|
| @@ -77,6 +76,73 @@ bool IsNoFrameRegion(i::Address address) {
|
|
|
| } // namespace
|
|
|
| +namespace internal {
|
| +namespace {
|
| +
|
| +#if defined(USE_SIMULATOR)
|
| +class SimulatorHelper {
|
| + public:
|
| + // Returns true if register values were successfully retrieved
|
| + // from the simulator, otherwise returns false.
|
| + static bool FillRegisters(Isolate* isolate, v8::RegisterState* state);
|
| +};
|
| +
|
| +bool SimulatorHelper::FillRegisters(Isolate* isolate,
|
| + v8::RegisterState* state) {
|
| + Simulator* simulator = isolate->thread_local_top()->simulator_;
|
| + // Check if there is active simulator.
|
| + if (simulator == NULL) return false;
|
| +#if V8_TARGET_ARCH_ARM
|
| + if (!simulator->has_bad_pc()) {
|
| + state->pc = reinterpret_cast<Address>(simulator->get_pc());
|
| + }
|
| + state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
|
| + state->fp =
|
| + reinterpret_cast<Address>(simulator->get_register(Simulator::r11));
|
| +#elif V8_TARGET_ARCH_ARM64
|
| + state->pc = reinterpret_cast<Address>(simulator->pc());
|
| + state->sp = reinterpret_cast<Address>(simulator->sp());
|
| + state->fp = reinterpret_cast<Address>(simulator->fp());
|
| +#elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
|
| + if (!simulator->has_bad_pc()) {
|
| + state->pc = reinterpret_cast<Address>(simulator->get_pc());
|
| + }
|
| + state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
|
| + state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
|
| +#elif V8_TARGET_ARCH_PPC
|
| + if (!simulator->has_bad_pc()) {
|
| + state->pc = reinterpret_cast<Address>(simulator->get_pc());
|
| + }
|
| + state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
|
| + state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
|
| +#elif V8_TARGET_ARCH_S390
|
| + if (!simulator->has_bad_pc()) {
|
| + state->pc = reinterpret_cast<Address>(simulator->get_pc());
|
| + }
|
| + state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
|
| + state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
|
| +#endif
|
| + if (state->sp == 0 || state->fp == 0) {
|
| + // It possible that the simulator is interrupted while it is updating
|
| + // the sp or fp register. ARM64 simulator does this in two steps:
|
| + // first setting it to zero and then setting it to the new value.
|
| + // Bailout if sp/fp doesn't contain the new value.
|
| + //
|
| + // FIXME: The above doesn't really solve the issue.
|
| + // If a 64-bit target is executed on a 32-bit host even the final
|
| + // write is non-atomic, so it might obtain a half of the result.
|
| + // Moreover as long as the register set code uses memcpy (as of now),
|
| + // it is not guaranteed to be atomic even when both host and target
|
| + // are of same bitness.
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +#endif // USE_SIMULATOR
|
| +
|
| +} // namespace
|
| +} // namespace internal
|
| +
|
| //
|
| // StackTracer implementation
|
| //
|
| @@ -85,35 +151,33 @@ DISABLE_ASAN void TickSample::Init(Isolate* v8_isolate,
|
| RecordCEntryFrame record_c_entry_frame,
|
| bool update_stats) {
|
| this->update_stats = update_stats;
|
| -
|
| SampleInfo info;
|
| - if (GetStackSample(v8_isolate, const_cast<RegisterState&>(regs),
|
| - record_c_entry_frame, reinterpret_cast<void**>(&stack[0]),
|
| - kMaxFramesCount, &info)) {
|
| - state = info.vm_state;
|
| - pc = regs.pc;
|
| - frames_count = static_cast<unsigned>(info.frames_count);
|
| - has_external_callback = info.external_callback_entry != nullptr;
|
| - if (has_external_callback) {
|
| - external_callback_entry = info.external_callback_entry;
|
| - } else if (frames_count) {
|
| - // sp register may point at an arbitrary place in memory, make
|
| - // sure MSAN doesn't complain about it.
|
| - MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(void*));
|
| - // Sample potential return address value for frameless invocation of
|
| - // stubs (we'll figure out later, if this value makes sense).
|
| - tos = i::Memory::Address_at(reinterpret_cast<i::Address>(regs.sp));
|
| - } else {
|
| - tos = nullptr;
|
| - }
|
| - } else {
|
| + if (!GetStackSample(v8_isolate, regs, record_c_entry_frame, stack,
|
| + kMaxFramesCount, &info)) {
|
| // It is executing JS but failed to collect a stack trace.
|
| // Mark the sample as spoiled.
|
| pc = nullptr;
|
| + return;
|
| + }
|
| + state = info.vm_state;
|
| + pc = regs.pc;
|
| + frames_count = static_cast<unsigned>(info.frames_count);
|
| + has_external_callback = info.external_callback_entry != nullptr;
|
| + if (has_external_callback) {
|
| + external_callback_entry = info.external_callback_entry;
|
| + } else if (frames_count) {
|
| + // sp register may point at an arbitrary place in memory, make
|
| + // sure MSAN doesn't complain about it.
|
| + MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(void*));
|
| + // Sample potential return address value for frameless invocation of
|
| + // stubs (we'll figure out later, if this value makes sense).
|
| + tos = i::Memory::Address_at(reinterpret_cast<i::Address>(regs.sp));
|
| + } else {
|
| + tos = nullptr;
|
| }
|
| }
|
|
|
| -bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& regs,
|
| +bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& state,
|
| RecordCEntryFrame record_c_entry_frame,
|
| void** frames, size_t frames_limit,
|
| v8::SampleInfo* sample_info) {
|
| @@ -125,10 +189,17 @@ bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& regs,
|
|
|
| i::Address js_entry_sp = isolate->js_entry_sp();
|
| if (js_entry_sp == nullptr) return true; // Not executing JS now.
|
| +
|
| +#if defined(USE_SIMULATOR)
|
| + v8::RegisterState regs;
|
| + if (!i::SimulatorHelper::FillRegisters(isolate, ®s)) return false;
|
| +#else
|
| + const v8::RegisterState& regs = state;
|
| +#endif
|
| DCHECK(regs.sp);
|
|
|
| if (regs.pc && IsNoFrameRegion(static_cast<i::Address>(regs.pc))) {
|
| - // Can't collect stack.
|
| + // The frame is not setup, so it'd be hard to iterate the stack. Bailout.
|
| return false;
|
| }
|
|
|
| @@ -183,59 +254,5 @@ void TickSample::Init(Isolate* isolate, const v8::RegisterState& state,
|
| timestamp = base::TimeTicks::HighResolutionNow();
|
| }
|
|
|
| -#if defined(USE_SIMULATOR)
|
| -bool SimulatorHelper::FillRegisters(Isolate* isolate,
|
| - v8::RegisterState* state) {
|
| - Simulator* simulator = isolate->thread_local_top()->simulator_;
|
| - // Check if there is active simulator.
|
| - if (simulator == NULL) return false;
|
| -#if V8_TARGET_ARCH_ARM
|
| - if (!simulator->has_bad_pc()) {
|
| - state->pc = reinterpret_cast<Address>(simulator->get_pc());
|
| - }
|
| - state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
|
| - state->fp =
|
| - reinterpret_cast<Address>(simulator->get_register(Simulator::r11));
|
| -#elif V8_TARGET_ARCH_ARM64
|
| - state->pc = reinterpret_cast<Address>(simulator->pc());
|
| - state->sp = reinterpret_cast<Address>(simulator->sp());
|
| - state->fp = reinterpret_cast<Address>(simulator->fp());
|
| -#elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
|
| - if (!simulator->has_bad_pc()) {
|
| - state->pc = reinterpret_cast<Address>(simulator->get_pc());
|
| - }
|
| - state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
|
| - state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
|
| -#elif V8_TARGET_ARCH_PPC
|
| - if (!simulator->has_bad_pc()) {
|
| - state->pc = reinterpret_cast<Address>(simulator->get_pc());
|
| - }
|
| - state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
|
| - state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
|
| -#elif V8_TARGET_ARCH_S390
|
| - if (!simulator->has_bad_pc()) {
|
| - state->pc = reinterpret_cast<Address>(simulator->get_pc());
|
| - }
|
| - state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
|
| - state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
|
| -#endif
|
| - if (state->sp == 0 || state->fp == 0) {
|
| - // It possible that the simulator is interrupted while it is updating
|
| - // the sp or fp register. ARM64 simulator does this in two steps:
|
| - // first setting it to zero and then setting it to the new value.
|
| - // Bailout if sp/fp doesn't contain the new value.
|
| - //
|
| - // FIXME: The above doesn't really solve the issue.
|
| - // If a 64-bit target is executed on a 32-bit host even the final
|
| - // write is non-atomic, so it might obtain a half of the result.
|
| - // Moreover as long as the register set code uses memcpy (as of now),
|
| - // it is not guaranteed to be atomic even when both host and target
|
| - // are of same bitness.
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -#endif // USE_SIMULATOR
|
| -
|
| } // namespace internal
|
| } // namespace v8
|
|
|