Commit b027b623 authored by lpy's avatar lpy Committed by Commit bot

Make Isolate::GetStackSample API support simulator

Currently GetStackSample doesn't support simulator, thus sampler is aware of
simulator, but since we are moving it out, it shouldn't have knowledge of
simulator. This patch moves the logic using simulator accessible
to Isolate::GetStackSample, so that it supports simulator.

BUG=v8:4956
LOG=n

Review-Url: https://codereview.chromium.org/1926863003
Cr-Commit-Position: refs/heads/master@{#35944}
parent 7741feb2
......@@ -7522,7 +7522,16 @@ bool Isolate::GetHeapObjectStatisticsAtLastGC(
void Isolate::GetStackSample(const RegisterState& state, void** frames,
size_t frames_limit, SampleInfo* sample_info) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
i::TickSample::GetStackSample(isolate, state, i::TickSample::kSkipCEntryFrame,
#if defined(USE_SIMULATOR)
RegisterState regs;
regs.pc = state.pc;
regs.sp = state.sp;
regs.fp = state.fp;
i::SimulatorHelper::FillRegisters(isolate, &regs);
#else
const RegisterState& regs = state;
#endif
i::TickSample::GetStackSample(isolate, regs, i::TickSample::kSkipCEntryFrame,
frames, frames_limit, sample_info);
}
......
......@@ -332,71 +332,57 @@ class Sampler::PlatformData : public PlatformDataCommon {
#if defined(USE_SIMULATOR)
class SimulatorHelper {
public:
inline bool Init(Isolate* isolate) {
simulator_ = isolate->thread_local_top()->simulator_;
// Check if there is active simulator.
return simulator_ != NULL;
}
inline void FillRegisters(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));
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
if (simulator_->sp() == 0 || simulator_->fp() == 0) {
// It's 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 a 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;
}
state->pc = reinterpret_cast<Address>(simulator_->pc());
state->sp = reinterpret_cast<Address>(simulator_->sp());
state->fp = reinterpret_cast<Address>(simulator_->fp());
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));
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));
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));
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;
}
private:
Simulator* simulator_;
};
return true;
}
#endif // USE_SIMULATOR
......@@ -487,14 +473,7 @@ void SignalHandler::CollectSample(void* context, Sampler* sampler) {
v8::RegisterState state;
#if defined(USE_SIMULATOR)
SimulatorHelper helper;
if (!helper.Init(isolate)) return;
helper.FillRegisters(&state);
// 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.
if (state.sp == 0 || state.fp == 0) return;
if (!SimulatorHelper::FillRegisters(isolate, &state)) return;
#else
// Extracting the sample from the context is extremely machine dependent.
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
......@@ -1023,11 +1002,6 @@ void Sampler::DoSample() {
HANDLE profiled_thread = platform_data()->profiled_thread();
if (profiled_thread == NULL) return;
#if defined(USE_SIMULATOR)
SimulatorHelper helper;
if (!helper.Init(isolate())) return;
#endif
const DWORD kSuspendFailed = static_cast<DWORD>(-1);
if (SuspendThread(profiled_thread) == kSuspendFailed) return;
......@@ -1038,7 +1012,10 @@ void Sampler::DoSample() {
if (GetThreadContext(profiled_thread, &context) != 0) {
v8::RegisterState state;
#if defined(USE_SIMULATOR)
helper.FillRegisters(&state);
if (!SimulatorHelper::FillRegisters(isolate(), &state)) {
ResumeThread(profiled_thread);
return;
}
#else
#if V8_HOST_ARCH_X64
state.pc = reinterpret_cast<Address>(context.Rip);
......
......@@ -141,6 +141,16 @@ class Sampler {
};
#if defined(USE_SIMULATOR)
class SimulatorHelper : AllStatic {
public:
// Returns true if register values were successfully retrieved
// from the simulator, otherwise returns false.
static bool FillRegisters(Isolate* isolate, v8::RegisterState* state);
};
#endif // USE_SIMULATOR
} // namespace internal
} // namespace v8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment