| Index: src/sampler.cc
|
| diff --git a/src/sampler.cc b/src/sampler.cc
|
| index 4e669ca6dc13611fdda5bacc728d2f1227592646..3b641fc448890d0080f2e2b8f9c09eb6c50b09f5 100644
|
| --- a/src/sampler.cc
|
| +++ b/src/sampler.cc
|
| @@ -173,6 +173,67 @@ class PlatformDataCommon : public Malloced {
|
| ThreadId profiled_thread_id_;
|
| };
|
|
|
| +
|
| +bool IsSamePage(byte* ptr1, byte* ptr2) {
|
| + const uint32_t kPageSize = 4096;
|
| + uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1);
|
| + return (reinterpret_cast<uintptr_t>(ptr1) & mask) ==
|
| + (reinterpret_cast<uintptr_t>(ptr2) & mask);
|
| +}
|
| +
|
| +
|
| +// Check if the code at specified address could potentially be a
|
| +// frame setup code.
|
| +bool IsNoFrameRegion(Address address) {
|
| + struct Pattern {
|
| + int bytes_count;
|
| + byte bytes[8];
|
| + int offsets[4];
|
| + };
|
| + byte* pc = reinterpret_cast<byte*>(address);
|
| + static Pattern patterns[] = {
|
| +#if V8_HOST_ARCH_IA32
|
| + // push %ebp
|
| + // mov %esp,%ebp
|
| + {3, {0x55, 0x89, 0xe5}, {0, 1, -1}},
|
| + // pop %ebp
|
| + // ret N
|
| + {2, {0x5d, 0xc2}, {0, 1, -1}},
|
| + // pop %ebp
|
| + // ret
|
| + {2, {0x5d, 0xc3}, {0, 1, -1}},
|
| +#elif V8_HOST_ARCH_X64
|
| + // pushq %rbp
|
| + // movq %rsp,%rbp
|
| + {4, {0x55, 0x48, 0x89, 0xe5}, {0, 1, -1}},
|
| + // popq %rbp
|
| + // ret N
|
| + {2, {0x5d, 0xc2}, {0, 1, -1}},
|
| + // popq %rbp
|
| + // ret
|
| + {2, {0x5d, 0xc3}, {0, 1, -1}},
|
| +#endif
|
| + {0, {}, {}}
|
| + };
|
| + for (Pattern* pattern = patterns; pattern->bytes_count; ++pattern) {
|
| + for (int* offset_ptr = pattern->offsets; *offset_ptr != -1; ++offset_ptr) {
|
| + int offset = *offset_ptr;
|
| + if (!offset || IsSamePage(pc, pc - offset)) {
|
| + if (!memcmp(pc - offset, pattern->bytes, pattern->bytes_count))
|
| + return true;
|
| + } else {
|
| + // It is not safe to examine bytes on another page as it might not be
|
| + // allocated thus causing a SEGFAULT.
|
| + // Check the pattern part that's on the same page and
|
| + // pessimistically assume it could be the entire pattern match.
|
| + if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset))
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| } // namespace
|
|
|
| #if defined(USE_SIGNALS)
|
| @@ -232,7 +293,9 @@ class SimulatorHelper {
|
|
|
| inline void FillRegisters(v8::RegisterState* state) {
|
| #if V8_TARGET_ARCH_ARM
|
| - state->pc = reinterpret_cast<Address>(simulator_->get_pc());
|
| + 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(
|
| @@ -243,19 +306,30 @@ class SimulatorHelper {
|
| // 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());
|
| #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
|
| - state->pc = reinterpret_cast<Address>(simulator_->get_pc());
|
| + 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
|
| - state->pc = reinterpret_cast<Address>(simulator_->get_pc());
|
| + 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 =
|
| @@ -592,6 +666,11 @@ DISABLE_ASAN void TickSample::Init(Isolate* isolate,
|
| Address js_entry_sp = isolate->js_entry_sp();
|
| if (js_entry_sp == 0) return; // Not executing JS now.
|
|
|
| + if (pc && IsNoFrameRegion(pc)) {
|
| + pc = 0;
|
| + return;
|
| + }
|
| +
|
| ExternalCallbackScope* scope = isolate->external_callback_scope();
|
| Address handler = Isolate::handler(isolate->thread_local_top());
|
| // If there is a handler on top of the external callback scope then
|
|
|