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