Commit aee3542f authored by alph's avatar alph Committed by Commit bot

[profiler] Emit runtime call stats into sampling profile

These are added to the sampler stack trace when RCS are
enabled.
Resource name for a RCS frame is reported as "V8Runtime".
Counter names match ones from src/counters.h

BUG=chromium:660428

Review-Url: https://codereview.chromium.org/2461003002
Cr-Commit-Position: refs/heads/master@{#40658}
parent 9b25707b
......@@ -499,6 +499,7 @@ class RuntimeCallTimer {
RuntimeCallTimer() {}
RuntimeCallCounter* counter() { return counter_; }
base::ElapsedTimer timer() { return timer_; }
RuntimeCallTimer* parent() const { return parent_; }
private:
friend class RuntimeCallStats;
......
......@@ -305,7 +305,7 @@ void CpuProfiler::StartProcessorIfNotStarted() {
// Disable logging when using the new implementation.
saved_is_logging_ = logger->is_logging_;
logger->is_logging_ = false;
generator_.reset(new ProfileGenerator(profiles_.get()));
generator_.reset(new ProfileGenerator(isolate_, profiles_.get()));
processor_.reset(new ProfilerEventsProcessor(isolate_, generator_.get(),
sampling_interval_));
logger->SetUpProfilerListener();
......
......@@ -648,8 +648,9 @@ void CpuProfilesCollection::AddPathToCurrentProfiles(
current_profiles_semaphore_.Signal();
}
ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
: profiles_(profiles) {}
ProfileGenerator::ProfileGenerator(Isolate* isolate,
CpuProfilesCollection* profiles)
: isolate_(isolate), profiles_(profiles) {}
void ProfileGenerator::RecordTickSample(const TickSample& sample) {
std::vector<CodeEntry*> entries;
......@@ -670,16 +671,14 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
// Don't use PC when in external callback code, as it can point
// inside callback's code, and we will erroneously report
// that a callback calls itself.
entries.push_back(code_map_.FindEntry(
reinterpret_cast<Address>(sample.external_callback_entry)));
entries.push_back(FindEntry(sample.external_callback_entry));
} else {
CodeEntry* pc_entry =
code_map_.FindEntry(reinterpret_cast<Address>(sample.pc));
CodeEntry* pc_entry = FindEntry(sample.pc);
// If there is no pc_entry we're likely in native code.
// Find out, if top of stack was pointing inside a JS function
// meaning that we have encountered a frameless invocation.
if (!pc_entry && !sample.has_external_callback) {
pc_entry = code_map_.FindEntry(reinterpret_cast<Address>(sample.tos));
pc_entry = FindEntry(sample.tos);
}
// If pc is in the function code before it set up stack frame or after the
// frame was destroyed SafeStackFrameIterator incorrectly thinks that
......@@ -712,8 +711,7 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
for (unsigned i = 0; i < sample.frames_count; ++i) {
Address stack_pos = reinterpret_cast<Address>(sample.stack[i]);
CodeEntry* entry = code_map_.FindEntry(stack_pos);
CodeEntry* entry = FindEntry(stack_pos);
if (entry) {
// Find out if the entry has an inlining stack associated.
int pc_offset =
......@@ -756,6 +754,22 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
sample.update_stats);
}
CodeEntry* ProfileGenerator::FindEntry(void* address) {
CodeEntry* entry = code_map_.FindEntry(reinterpret_cast<Address>(address));
if (!entry) {
RuntimeCallStats* rcs = isolate_->counters()->runtime_call_stats();
void* start = reinterpret_cast<void*>(rcs);
void* end = reinterpret_cast<void*>(rcs + 1);
if (start <= address && address < end) {
RuntimeCallCounter* counter =
reinterpret_cast<RuntimeCallCounter*>(address);
entry = new CodeEntry(CodeEventListener::FUNCTION_TAG, counter->name,
CodeEntry::kEmptyNamePrefix, "native V8Runtime");
code_map_.AddCode(reinterpret_cast<Address>(address), entry, 1);
}
}
return entry;
}
CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
switch (tag) {
......
......@@ -379,15 +379,17 @@ class CpuProfilesCollection {
class ProfileGenerator {
public:
explicit ProfileGenerator(CpuProfilesCollection* profiles);
ProfileGenerator(Isolate* isolate, CpuProfilesCollection* profiles);
void RecordTickSample(const TickSample& sample);
CodeMap* code_map() { return &code_map_; }
private:
CodeEntry* FindEntry(void* address);
CodeEntry* EntryForVMState(StateTag tag);
Isolate* isolate_;
CpuProfilesCollection* profiles_;
CodeMap code_map_;
......
......@@ -5,6 +5,7 @@
#include "src/profiler/tick-sample.h"
#include "include/v8-profiler.h"
#include "src/counters.h"
#include "src/frames-inl.h"
#include "src/msan.h"
#include "src/simulator.h"
......@@ -237,7 +238,15 @@ bool TickSample::GetStackSample(Isolate* v8_isolate, RegisterState* regs,
it.top_frame_type() == internal::StackFrame::BUILTIN_EXIT)) {
frames[i++] = isolate->c_function();
}
i::RuntimeCallTimer* timer =
isolate->counters()->runtime_call_stats()->current_timer();
for (; !it.done() && i < frames_limit; it.Advance()) {
while (timer && reinterpret_cast<i::Address>(timer) < it.frame()->fp() &&
i < frames_limit) {
frames[i++] = reinterpret_cast<i::Address>(timer->counter());
timer = timer->parent();
}
if (i == frames_limit) break;
if (!it.frame()->is_interpreted()) {
frames[i++] = it.frame()->pc();
continue;
......
......@@ -71,10 +71,11 @@ static const char* reason(const i::DeoptimizeReason reason) {
}
TEST(StartStop) {
CpuProfilesCollection profiles(CcTest::i_isolate());
ProfileGenerator generator(&profiles);
i::Isolate* isolate = CcTest::i_isolate();
CpuProfilesCollection profiles(isolate);
ProfileGenerator generator(isolate, &profiles);
std::unique_ptr<ProfilerEventsProcessor> processor(
new ProfilerEventsProcessor(CcTest::i_isolate(), &generator,
new ProfilerEventsProcessor(isolate, &generator,
v8::base::TimeDelta::FromMicroseconds(100)));
processor->Start();
processor->StopSynchronously();
......@@ -157,10 +158,9 @@ TEST(CodeEvents) {
i::AbstractCode* args4_code = CreateCode(&env);
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfileGenerator* generator = new ProfileGenerator(profiles);
ProfilerEventsProcessor* processor =
new ProfilerEventsProcessor(CcTest::i_isolate(), generator,
v8::base::TimeDelta::FromMicroseconds(100));
ProfileGenerator* generator = new ProfileGenerator(isolate, profiles);
ProfilerEventsProcessor* processor = new ProfilerEventsProcessor(
isolate, generator, v8::base::TimeDelta::FromMicroseconds(100));
CpuProfiler profiler(isolate, profiles, generator, processor);
profiles->StartProfiling("", false);
processor->Start();
......@@ -226,7 +226,7 @@ TEST(TickEvents) {
i::AbstractCode* frame3_code = CreateCode(&env);
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfileGenerator* generator = new ProfileGenerator(profiles);
ProfileGenerator* generator = new ProfileGenerator(isolate, profiles);
ProfilerEventsProcessor* processor =
new ProfilerEventsProcessor(CcTest::i_isolate(), generator,
v8::base::TimeDelta::FromMicroseconds(100));
......@@ -299,7 +299,7 @@ TEST(Issue1398) {
i::AbstractCode* code = CreateCode(&env);
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfileGenerator* generator = new ProfileGenerator(profiles);
ProfileGenerator* generator = new ProfileGenerator(isolate, profiles);
ProfilerEventsProcessor* processor =
new ProfilerEventsProcessor(CcTest::i_isolate(), generator,
v8::base::TimeDelta::FromMicroseconds(100));
......@@ -1073,7 +1073,7 @@ static void TickLines(bool optimize) {
CHECK(code_address);
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfileGenerator* generator = new ProfileGenerator(profiles);
ProfileGenerator* generator = new ProfileGenerator(isolate, profiles);
ProfilerEventsProcessor* processor =
new ProfilerEventsProcessor(CcTest::i_isolate(), generator,
v8::base::TimeDelta::FromMicroseconds(100));
......
......@@ -344,11 +344,12 @@ class TestSetup {
TEST(RecordTickSample) {
TestSetup test_setup;
CpuProfilesCollection profiles(CcTest::i_isolate());
CpuProfiler profiler(CcTest::i_isolate());
i::Isolate* isolate = CcTest::i_isolate();
CpuProfilesCollection profiles(isolate);
CpuProfiler profiler(isolate);
profiles.set_cpu_profiler(&profiler);
profiles.StartProfiling("", false);
ProfileGenerator generator(&profiles);
ProfileGenerator generator(isolate, &profiles);
CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::Logger::FUNCTION_TAG, "bbb");
CodeEntry* entry3 = new CodeEntry(i::Logger::FUNCTION_TAG, "ccc");
......@@ -416,11 +417,12 @@ static void CheckNodeIds(ProfileNode* node, unsigned* expectedId) {
TEST(SampleIds) {
TestSetup test_setup;
CpuProfilesCollection profiles(CcTest::i_isolate());
CpuProfiler profiler(CcTest::i_isolate());
i::Isolate* isolate = CcTest::i_isolate();
CpuProfilesCollection profiles(isolate);
CpuProfiler profiler(isolate);
profiles.set_cpu_profiler(&profiler);
profiles.StartProfiling("", true);
ProfileGenerator generator(&profiles);
ProfileGenerator generator(isolate, &profiles);
CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::Logger::FUNCTION_TAG, "bbb");
CodeEntry* entry3 = new CodeEntry(i::Logger::FUNCTION_TAG, "ccc");
......@@ -473,11 +475,12 @@ TEST(SampleIds) {
TEST(NoSamples) {
TestSetup test_setup;
CpuProfilesCollection profiles(CcTest::i_isolate());
CpuProfiler profiler(CcTest::i_isolate());
i::Isolate* isolate = CcTest::i_isolate();
CpuProfilesCollection profiles(isolate);
CpuProfiler profiler(isolate);
profiles.set_cpu_profiler(&profiler);
profiles.StartProfiling("", false);
ProfileGenerator generator(&profiles);
ProfileGenerator generator(isolate, &profiles);
CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa");
generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
......
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