Index: src/profiler/tick-sample.cc |
diff --git a/src/profiler/tick-sample.cc b/src/profiler/tick-sample.cc |
index 87bfe60655632d08027d1ea4361b9476681d4ddf..8b7fe2c73ac6aceb20a324925a1331042a0f727b 100644 |
--- a/src/profiler/tick-sample.cc |
+++ b/src/profiler/tick-sample.cc |
@@ -11,6 +11,7 @@ |
#include "src/vm-state-inl.h" |
namespace v8 { |
+ |
namespace { |
bool IsSamePage(i::byte* ptr1, i::byte* ptr2) { |
@@ -76,67 +77,6 @@ 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, RegisterState* state) { |
- Simulator* simulator = isolate->thread_local_top()->simulator_; |
- // Check if there is active simulator. |
- if (simulator == nullptr) return false; |
-#if V8_TARGET_ARCH_ARM |
- if (simulator->has_bad_pc()) return false; |
- state->pc = reinterpret_cast<void*>(simulator->get_pc()); |
- state->sp = reinterpret_cast<void*>(simulator->get_register(Simulator::sp)); |
- state->fp = reinterpret_cast<void*>(simulator->get_register(Simulator::r11)); |
-#elif V8_TARGET_ARCH_ARM64 |
- state->pc = reinterpret_cast<void*>(simulator->pc()); |
- state->sp = reinterpret_cast<void*>(simulator->sp()); |
- state->fp = reinterpret_cast<void*>(simulator->fp()); |
-#elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 |
- if (simulator->has_bad_pc()) return false; |
- state->pc = reinterpret_cast<void*>(simulator->get_pc()); |
- state->sp = reinterpret_cast<void*>(simulator->get_register(Simulator::sp)); |
- state->fp = reinterpret_cast<void*>(simulator->get_register(Simulator::fp)); |
-#elif V8_TARGET_ARCH_PPC |
- if (simulator->has_bad_pc()) return false; |
- state->pc = reinterpret_cast<void*>(simulator->get_pc()); |
- state->sp = reinterpret_cast<void*>(simulator->get_register(Simulator::sp)); |
- state->fp = reinterpret_cast<void*>(simulator->get_register(Simulator::fp)); |
-#elif V8_TARGET_ARCH_S390 |
- if (simulator->has_bad_pc()) return false; |
- state->pc = reinterpret_cast<void*>(simulator->get_pc()); |
- state->sp = reinterpret_cast<void*>(simulator->get_register(Simulator::sp)); |
- state->fp = reinterpret_cast<void*>(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. |
- // |
- // TODO(alph): 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 |
// |
@@ -145,33 +85,35 @@ 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, regs, record_c_entry_frame, stack, |
- kMaxFramesCount, &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 { |
// 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& state, |
+bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& regs, |
RecordCEntryFrame record_c_entry_frame, |
void** frames, size_t frames_limit, |
v8::SampleInfo* sample_info) { |
@@ -183,17 +125,10 @@ bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& state, |
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))) { |
- // The frame is not setup, so it'd be hard to iterate the stack. Bailout. |
+ // Can't collect stack. |
return false; |
} |
@@ -248,5 +183,59 @@ 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 |