Commit 4af2bb9e authored by machenbach's avatar machenbach Committed by Commit bot

Revert three commits due to cpu-profiler failures.

Revert "Move SimulatorHelper into V8 out of profiler clients."

This reverts commit b8372411.

Revert "Make use of v8::TickSample instead of v8::internal::TickSample in logger."

This reverts commit c3a16f0a.

Revert "Clean up SimulatorHelper code."

This reverts commit 8ee236e1.

BUG=v8:5193
TBR=alph@chromium.org, yangguo@chromium.org

Review-Url: https://codereview.chromium.org/2138643003
Cr-Commit-Position: refs/heads/master@{#37626}
parent 59705072
......@@ -7656,13 +7656,20 @@ bool Isolate::GetHeapCodeAndMetadataStatistics(
void Isolate::GetStackSample(const RegisterState& state, void** frames,
size_t frames_limit, SampleInfo* sample_info) {
if (TickSample::GetStackSample(this, state, TickSample::kSkipCEntryFrame,
frames, frames_limit, sample_info)) {
#if defined(USE_SIMULATOR)
RegisterState regs;
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
if (!i::SimulatorHelper::FillRegisters(isolate, &regs)) {
sample_info->frames_count = 0;
sample_info->vm_state = OTHER;
sample_info->external_callback_entry = nullptr;
return;
}
sample_info->frames_count = 0;
sample_info->vm_state = OTHER;
sample_info->external_callback_entry = nullptr;
#else
const RegisterState& regs = state;
#endif
TickSample::GetStackSample(this, regs, TickSample::kSkipCEntryFrame, frames,
frames_limit, sample_info);
}
size_t Isolate::NumberOfPhantomHandleResetsSinceLastCall() {
......
......@@ -7,7 +7,6 @@
#include <cstdarg>
#include <sstream>
#include "include/v8-profiler.h"
#include "src/bailout-reason.h"
#include "src/base/platform/platform.h"
#include "src/bootstrapper.h"
......@@ -22,7 +21,9 @@
#include "src/log-utils.h"
#include "src/macro-assembler.h"
#include "src/perf-jit.h"
#include "src/profiler/cpu-profiler-inl.h"
#include "src/profiler/profiler-listener.h"
#include "src/profiler/tick-sample.h"
#include "src/runtime-profiler.h"
#include "src/string-stream.h"
#include "src/vm-state-inl.h"
......@@ -30,6 +31,7 @@
namespace v8 {
namespace internal {
#define DECLARE_EVENT(ignore1, name) name,
static const char* kLogEventsNames[CodeEventListener::NUMBER_OF_LOG_EVENTS] = {
LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)};
......@@ -555,7 +557,7 @@ class Profiler: public base::Thread {
void Disengage();
// Inserts collected profiling data into buffer.
void Insert(v8::TickSample* sample) {
void Insert(TickSample* sample) {
if (paused_)
return;
......@@ -576,7 +578,7 @@ class Profiler: public base::Thread {
private:
// Waits for a signal and removes profiling data.
bool Remove(v8::TickSample* sample) {
bool Remove(TickSample* sample) {
buffer_semaphore_.Wait(); // Wait for an element.
*sample = buffer_[base::NoBarrier_Load(&tail_)];
bool result = overflow_;
......@@ -593,7 +595,7 @@ class Profiler: public base::Thread {
// Cyclic buffer for communicating profiling samples
// between the signal handler and the worker thread.
static const int kBufferSize = 128;
v8::TickSample buffer_[kBufferSize]; // Buffer storage.
TickSample buffer_[kBufferSize]; // Buffer storage.
int head_; // Index to the buffer head.
base::Atomic32 tail_; // Index to the buffer tail.
bool overflow_; // Tell whether a buffer overflow has occurred.
......@@ -617,10 +619,10 @@ class Profiler: public base::Thread {
//
class Ticker: public sampler::Sampler {
public:
Ticker(Isolate* isolate, int interval)
: sampler::Sampler(reinterpret_cast<v8::Isolate*>(isolate)),
profiler_(nullptr),
sampling_thread_(new SamplingThread(this, interval)) {}
Ticker(Isolate* isolate, int interval):
sampler::Sampler(reinterpret_cast<v8::Isolate*>(isolate)),
profiler_(NULL),
sampling_thread_(new SamplingThread(this, interval)) {}
~Ticker() {
if (IsActive()) Stop();
......@@ -628,7 +630,7 @@ class Ticker: public sampler::Sampler {
}
void SetProfiler(Profiler* profiler) {
DCHECK(profiler_ == nullptr);
DCHECK(profiler_ == NULL);
profiler_ = profiler;
IncreaseProfilingDepth();
if (!IsActive()) Start();
......@@ -636,7 +638,7 @@ class Ticker: public sampler::Sampler {
}
void ClearProfiler() {
profiler_ = nullptr;
profiler_ = NULL;
if (IsActive()) Stop();
DecreaseProfilingDepth();
sampling_thread_->Join();
......@@ -644,8 +646,15 @@ class Ticker: public sampler::Sampler {
void SampleStack(const v8::RegisterState& state) override {
if (!profiler_) return;
v8::TickSample sample;
sample.Init(isolate(), state, v8::TickSample::kIncludeCEntryFrame, true);
v8::Isolate* v8_isolate = isolate();
Isolate* i_isolate = reinterpret_cast<Isolate*>(v8_isolate);
#if defined(USE_SIMULATOR)
if (!SimulatorHelper::FillRegisters(i_isolate,
const_cast<v8::RegisterState*>(&state)))
return;
#endif
TickSample sample;
sample.Init(i_isolate, state, TickSample::kIncludeCEntryFrame, true);
profiler_->Insert(&sample);
}
......@@ -705,7 +714,7 @@ void Profiler::Disengage() {
// inserting a fake element in the queue and then wait for
// the thread to terminate.
base::NoBarrier_Store(&running_, 0);
v8::TickSample sample;
TickSample sample;
// Reset 'paused_' flag, otherwise semaphore may not be signalled.
resume();
Insert(&sample);
......@@ -716,7 +725,7 @@ void Profiler::Disengage() {
void Profiler::Run() {
v8::TickSample sample;
TickSample sample;
bool overflow = Remove(&sample);
while (base::NoBarrier_Load(&running_)) {
LOG(isolate_, TickEvent(&sample, overflow));
......@@ -1358,7 +1367,7 @@ void Logger::RuntimeCallTimerEvent() {
msg.WriteToLogFile();
}
void Logger::TickEvent(v8::TickSample* sample, bool overflow) {
void Logger::TickEvent(TickSample* sample, bool overflow) {
if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
if (FLAG_runtime_call_stats) {
RuntimeCallTimerEvent();
......
......@@ -17,7 +17,9 @@
namespace v8 {
struct TickSample;
namespace base {
class Semaphore;
}
namespace sampler {
class Sampler;
......@@ -63,15 +65,11 @@ namespace internal {
class CodeEventListener;
class CpuProfiler;
class Isolate;
class JitLogger;
class Log;
class LowLevelLogger;
class PerfBasicLogger;
class PerfJitLogger;
class Profiler;
class ProfilerListener;
class RuntimeCallTimer;
class Ticker;
class RuntimeCallTimer;
struct TickSample;
#undef LOG
#define LOG(isolate, Call) \
......@@ -86,6 +84,12 @@ class Ticker;
if (logger->is_logging_code_events()) logger->Call; \
} while (false)
class JitLogger;
class PerfBasicLogger;
class LowLevelLogger;
class PerfJitLogger;
class ProfilerListener;
class Logger : public CodeEventListener {
public:
enum StartEnd { START = 0, END = 1 };
......
......@@ -23,11 +23,18 @@ class CpuSampler : public sampler::Sampler {
: sampler::Sampler(reinterpret_cast<v8::Isolate*>(isolate)),
processor_(processor) {}
void SampleStack(const v8::RegisterState& regs) override {
void SampleStack(const v8::RegisterState& state) override {
v8::Isolate* v8_isolate = isolate();
Isolate* i_isolate = reinterpret_cast<Isolate*>(v8_isolate);
#if defined(USE_SIMULATOR)
v8::RegisterState regs;
if (!SimulatorHelper::FillRegisters(i_isolate, &regs)) return;
#else
const v8::RegisterState& regs = state;
#endif
TickSample* sample = processor_->StartTickSample();
if (sample == nullptr) return;
Isolate* isolate = reinterpret_cast<Isolate*>(this->isolate());
sample->Init(isolate, regs, TickSample::kIncludeCEntryFrame, true);
if (sample == NULL) return;
sample->Init(i_isolate, regs, TickSample::kIncludeCEntryFrame, true);
if (is_counting_samples_ && !sample->timestamp.IsNull()) {
if (sample->state == JS) ++js_sample_count_;
if (sample->state == EXTERNAL) ++external_sample_count_;
......
......@@ -12,10 +12,11 @@
#include "src/profiler/strings-storage.h"
namespace v8 {
namespace internal {
struct TickSample;
namespace internal {
// Provides a mapping from the offsets within generated code to
// the source line.
class JITLineInfoTable : public Malloced {
......
......@@ -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, &regs)) 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
......@@ -15,11 +15,21 @@ namespace internal {
class Isolate;
struct TickSample : public v8::TickSample {
TickSample() : v8::TickSample() {}
void Init(Isolate* isolate, const v8::RegisterState& state,
RecordCEntryFrame record_c_entry_frame, bool update_stats);
base::TimeTicks timestamp;
};
#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);
};
#endif // USE_SIMULATOR
} // namespace internal
} // namespace v8
......
......@@ -41,9 +41,10 @@ class TestSampler : public Sampler {
explicit TestSampler(Isolate* isolate) : Sampler(isolate) {}
void SampleStack(const v8::RegisterState& regs) override {
void* frames[kMaxFramesCount];
void* frames[Sampler::kMaxFramesCount];
SampleInfo sample_info;
isolate()->GetStackSample(regs, frames, kMaxFramesCount, &sample_info);
isolate()->GetStackSample(regs, reinterpret_cast<void**>(frames),
Sampler::kMaxFramesCount, &sample_info);
if (is_counting_samples_) {
if (sample_info.vm_state == JS) ++js_sample_count_;
if (sample_info.vm_state == EXTERNAL) ++external_sample_count_;
......
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