| Index: src/profiler/sampler.cc
|
| diff --git a/src/profiler/sampler.cc b/src/profiler/sampler.cc
|
| index 055c9c83292ff99b4b4c8353b4656a2ed00f2825..ae47dca1504ed094448329f7b163450ee96016d0 100644
|
| --- a/src/profiler/sampler.cc
|
| +++ b/src/profiler/sampler.cc
|
| @@ -44,13 +44,10 @@
|
|
|
| #include "src/base/atomic-utils.h"
|
| #include "src/base/platform/platform.h"
|
| -#include "src/flags.h"
|
| -#include "src/frames-inl.h"
|
| -#include "src/log.h"
|
| #include "src/profiler/cpu-profiler-inl.h"
|
| +#include "src/profiler/tick-sample.h"
|
| #include "src/simulator.h"
|
| #include "src/v8threads.h"
|
| -#include "src/vm-state-inl.h"
|
|
|
|
|
| #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
|
| @@ -175,68 +172,6 @@ class PlatformDataCommon : public Malloced {
|
| };
|
|
|
|
|
| -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)) {
|
| - MSAN_MEMORY_IS_INITIALIZED(pc - offset, pattern->bytes_count);
|
| - 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.
|
| - MSAN_MEMORY_IS_INITIALIZED(pc, pattern->bytes_count - offset);
|
| - if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset))
|
| - return true;
|
| - }
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| typedef List<Sampler*> SamplerList;
|
|
|
| #if defined(USE_SIGNALS)
|
| @@ -331,61 +266,6 @@ class Sampler::PlatformData : public PlatformDataCommon {
|
| #endif
|
|
|
|
|
| -#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
|
| -
|
| -
|
| #if defined(USE_SIGNALS)
|
|
|
| class SignalHandler : public AllStatic {
|
| @@ -811,103 +691,6 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
|
| #endif // USE_SIGNALs
|
|
|
|
|
| -//
|
| -// StackTracer implementation
|
| -//
|
| -DISABLE_ASAN void TickSample::Init(Isolate* isolate,
|
| - const v8::RegisterState& regs,
|
| - RecordCEntryFrame record_c_entry_frame,
|
| - bool update_stats) {
|
| - timestamp = base::TimeTicks::HighResolutionNow();
|
| - pc = reinterpret_cast<Address>(regs.pc);
|
| - state = isolate->current_vm_state();
|
| - this->update_stats = update_stats;
|
| -
|
| - // Avoid collecting traces while doing GC.
|
| - if (state == GC) return;
|
| -
|
| - Address js_entry_sp = isolate->js_entry_sp();
|
| - if (js_entry_sp == 0) return; // Not executing JS now.
|
| -
|
| - if (pc && IsNoFrameRegion(pc)) {
|
| - // Can't collect stack. Mark the sample as spoiled.
|
| - timestamp = base::TimeTicks();
|
| - 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
|
| - // we have already entrered JavaScript again and the external callback
|
| - // is not the top function.
|
| - if (scope && scope->scope_address() < handler) {
|
| - external_callback_entry = *scope->callback_entrypoint_address();
|
| - has_external_callback = true;
|
| - } else {
|
| - // 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(Address));
|
| - // Sample potential return address value for frameless invocation of
|
| - // stubs (we'll figure out later, if this value makes sense).
|
| - tos = Memory::Address_at(reinterpret_cast<Address>(regs.sp));
|
| - has_external_callback = false;
|
| - }
|
| -
|
| - SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp),
|
| - reinterpret_cast<Address>(regs.sp), js_entry_sp);
|
| - top_frame_type = it.top_frame_type();
|
| -
|
| - SampleInfo info;
|
| - GetStackSample(isolate, regs, record_c_entry_frame,
|
| - reinterpret_cast<void**>(&stack[0]), kMaxFramesCount, &info);
|
| - frames_count = static_cast<unsigned>(info.frames_count);
|
| - if (!frames_count) {
|
| - // It is executing JS but failed to collect a stack trace.
|
| - // Mark the sample as spoiled.
|
| - timestamp = base::TimeTicks();
|
| - pc = 0;
|
| - }
|
| -}
|
| -
|
| -
|
| -void TickSample::GetStackSample(Isolate* isolate, const v8::RegisterState& regs,
|
| - RecordCEntryFrame record_c_entry_frame,
|
| - void** frames, size_t frames_limit,
|
| - v8::SampleInfo* sample_info) {
|
| - sample_info->frames_count = 0;
|
| - sample_info->vm_state = isolate->current_vm_state();
|
| - if (sample_info->vm_state == GC) return;
|
| -
|
| - Address js_entry_sp = isolate->js_entry_sp();
|
| - if (js_entry_sp == 0) return; // Not executing JS now.
|
| -
|
| - SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp),
|
| - reinterpret_cast<Address>(regs.sp), js_entry_sp);
|
| - size_t i = 0;
|
| - if (record_c_entry_frame == kIncludeCEntryFrame && !it.done() &&
|
| - it.top_frame_type() == StackFrame::EXIT) {
|
| - frames[i++] = isolate->c_function();
|
| - }
|
| - while (!it.done() && i < frames_limit) {
|
| - if (it.frame()->is_interpreted()) {
|
| - // For interpreted frames use the bytecode array pointer as the pc.
|
| - InterpretedFrame* frame = static_cast<InterpretedFrame*>(it.frame());
|
| - // Since the sampler can interrupt execution at any point the
|
| - // bytecode_array might be garbage, so don't dereference it.
|
| - Address bytecode_array =
|
| - reinterpret_cast<Address>(frame->GetBytecodeArray()) - kHeapObjectTag;
|
| - frames[i++] = bytecode_array + BytecodeArray::kHeaderSize +
|
| - frame->GetBytecodeOffset();
|
| - } else {
|
| - frames[i++] = it.frame()->pc();
|
| - }
|
| - it.Advance();
|
| - }
|
| - sample_info->frames_count = i;
|
| -}
|
| -
|
| -
|
| void Sampler::SetUp() {
|
| #if defined(USE_SIGNALS)
|
| SignalHandler::SetUp();
|
|
|