Commit b0841272 authored by Andrew Comminos's avatar Andrew Comminos Committed by Commit Bot

[cpu-profiler] Split out debug mode for CPU profiler naming

Adds a new flag to CpuProfiler to control whether or not "debug" names
(potentially inferred from scope) are used for captured frames
associated with a SharedFunctionInfo instance.

Bug: v8:9135
Change-Id: Ia1db20e389f3d0beb60eb47798820fb11d501c88
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1583042
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarPeter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61015}
parent 11b7308f
...@@ -297,6 +297,15 @@ enum CpuProfilingMode { ...@@ -297,6 +297,15 @@ enum CpuProfilingMode {
kCallerLineNumbers, kCallerLineNumbers,
}; };
// Determines how names are derived for functions sampled.
enum CpuProfilingNamingMode {
// Use the immediate name of functions at compilation time.
kStandardNaming,
// Use more verbose naming for functions without names, inferred from scope
// where possible.
kDebugNaming,
};
/** /**
* Interface for controlling CPU profiling. Instance of the * Interface for controlling CPU profiling. Instance of the
* profiler can be created using v8::CpuProfiler::New method. * profiler can be created using v8::CpuProfiler::New method.
...@@ -308,7 +317,8 @@ class V8_EXPORT CpuProfiler { ...@@ -308,7 +317,8 @@ class V8_EXPORT CpuProfiler {
* initialized. The profiler object must be disposed after use by calling * initialized. The profiler object must be disposed after use by calling
* |Dispose| method. * |Dispose| method.
*/ */
static CpuProfiler* New(Isolate* isolate); static CpuProfiler* New(Isolate* isolate,
CpuProfilingNamingMode = kDebugNaming);
/** /**
* Synchronously collect current stack sample in all profilers attached to * Synchronously collect current stack sample in all profilers attached to
......
...@@ -10125,9 +10125,9 @@ int CpuProfile::GetSamplesCount() const { ...@@ -10125,9 +10125,9 @@ int CpuProfile::GetSamplesCount() const {
return reinterpret_cast<const i::CpuProfile*>(this)->samples_count(); return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
} }
CpuProfiler* CpuProfiler::New(Isolate* isolate) { CpuProfiler* CpuProfiler::New(Isolate* isolate, CpuProfilingNamingMode mode) {
return reinterpret_cast<CpuProfiler*>( return reinterpret_cast<CpuProfiler*>(
new i::CpuProfiler(reinterpret_cast<i::Isolate*>(isolate))); new i::CpuProfiler(reinterpret_cast<i::Isolate*>(isolate), mode));
} }
void CpuProfiler::Dispose() { delete reinterpret_cast<i::CpuProfiler*>(this); } void CpuProfiler::Dispose() { delete reinterpret_cast<i::CpuProfiler*>(this); }
......
...@@ -310,14 +310,16 @@ DEFINE_LAZY_LEAKY_OBJECT_GETTER(CpuProfilersManager, GetProfilersManager) ...@@ -310,14 +310,16 @@ DEFINE_LAZY_LEAKY_OBJECT_GETTER(CpuProfilersManager, GetProfilersManager)
} // namespace } // namespace
CpuProfiler::CpuProfiler(Isolate* isolate) CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode)
: CpuProfiler(isolate, new CpuProfilesCollection(isolate), nullptr, : CpuProfiler(isolate, naming_mode, new CpuProfilesCollection(isolate),
nullptr) {} nullptr, nullptr) {}
CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilesCollection* test_profiles, CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
CpuProfilesCollection* test_profiles,
ProfileGenerator* test_generator, ProfileGenerator* test_generator,
ProfilerEventsProcessor* test_processor) ProfilerEventsProcessor* test_processor)
: isolate_(isolate), : isolate_(isolate),
naming_mode_(naming_mode),
sampling_interval_(base::TimeDelta::FromMicroseconds( sampling_interval_(base::TimeDelta::FromMicroseconds(
FLAG_cpu_profiler_sampling_interval)), FLAG_cpu_profiler_sampling_interval)),
profiles_(test_profiles), profiles_(test_profiles),
...@@ -409,7 +411,8 @@ void CpuProfiler::StartProcessorIfNotStarted() { ...@@ -409,7 +411,8 @@ void CpuProfiler::StartProcessorIfNotStarted() {
if (profiler_listener_) { if (profiler_listener_) {
profiler_listener_->set_observer(processor_.get()); profiler_listener_->set_observer(processor_.get());
} else { } else {
profiler_listener_.reset(new ProfilerListener(isolate_, processor_.get())); profiler_listener_.reset(
new ProfilerListener(isolate_, processor_.get(), naming_mode_));
} }
logger->AddCodeEventListener(profiler_listener_.get()); logger->AddCodeEventListener(profiler_listener_.get());
is_profiling_ = true; is_profiling_ = true;
......
...@@ -216,10 +216,10 @@ class V8_EXPORT_PRIVATE SamplingEventsProcessor ...@@ -216,10 +216,10 @@ class V8_EXPORT_PRIVATE SamplingEventsProcessor
class V8_EXPORT_PRIVATE CpuProfiler { class V8_EXPORT_PRIVATE CpuProfiler {
public: public:
explicit CpuProfiler(Isolate* isolate); explicit CpuProfiler(Isolate* isolate, CpuProfilingNamingMode = kDebugNaming);
CpuProfiler(Isolate* isolate, CpuProfilesCollection* profiles, CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
ProfileGenerator* test_generator, CpuProfilesCollection* profiles, ProfileGenerator* test_generator,
ProfilerEventsProcessor* test_processor); ProfilerEventsProcessor* test_processor);
~CpuProfiler(); ~CpuProfiler();
...@@ -227,6 +227,7 @@ class V8_EXPORT_PRIVATE CpuProfiler { ...@@ -227,6 +227,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
static void CollectSample(Isolate* isolate); static void CollectSample(Isolate* isolate);
typedef v8::CpuProfilingMode ProfilingMode; typedef v8::CpuProfilingMode ProfilingMode;
typedef v8::CpuProfilingNamingMode NamingMode;
void set_sampling_interval(base::TimeDelta value); void set_sampling_interval(base::TimeDelta value);
void set_use_precise_sampling(bool); void set_use_precise_sampling(bool);
...@@ -260,6 +261,7 @@ class V8_EXPORT_PRIVATE CpuProfiler { ...@@ -260,6 +261,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
void CreateEntriesForRuntimeCallStats(); void CreateEntriesForRuntimeCallStats();
Isolate* const isolate_; Isolate* const isolate_;
const NamingMode naming_mode_;
base::TimeDelta sampling_interval_; base::TimeDelta sampling_interval_;
bool use_precise_sampling_ = true; bool use_precise_sampling_ = true;
std::unique_ptr<CpuProfilesCollection> profiles_; std::unique_ptr<CpuProfilesCollection> profiles_;
......
...@@ -21,8 +21,9 @@ namespace v8 { ...@@ -21,8 +21,9 @@ namespace v8 {
namespace internal { namespace internal {
ProfilerListener::ProfilerListener(Isolate* isolate, ProfilerListener::ProfilerListener(Isolate* isolate,
CodeEventObserver* observer) CodeEventObserver* observer,
: isolate_(isolate), observer_(observer) {} CpuProfilingNamingMode naming_mode)
: isolate_(isolate), observer_(observer), naming_mode_(naming_mode) {}
ProfilerListener::~ProfilerListener() = default; ProfilerListener::~ProfilerListener() = default;
...@@ -163,7 +164,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, ...@@ -163,7 +164,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
std::unique_ptr<CodeEntry> inline_entry = std::unique_ptr<CodeEntry> inline_entry =
base::make_unique<CodeEntry>( base::make_unique<CodeEntry>(
tag, GetName(pos_info.shared->DebugName()), resource_name, tag, GetFunctionName(*pos_info.shared), resource_name,
start_pos_info.line + 1, start_pos_info.column + 1, nullptr, start_pos_info.line + 1, start_pos_info.column + 1, nullptr,
code->InstructionStart(), inline_is_shared_cross_origin); code->InstructionStart(), inline_is_shared_cross_origin);
inline_entry->FillFunctionInfo(*pos_info.shared); inline_entry->FillFunctionInfo(*pos_info.shared);
...@@ -182,7 +183,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, ...@@ -182,7 +183,7 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
} }
} }
rec->entry = rec->entry =
new CodeEntry(tag, GetName(shared->DebugName()), new CodeEntry(tag, GetFunctionName(shared),
GetName(InferScriptName(script_name, shared)), line, column, GetName(InferScriptName(script_name, shared)), line, column,
std::move(line_table), abstract_code->InstructionStart(), std::move(line_table), abstract_code->InstructionStart(),
is_shared_cross_origin); is_shared_cross_origin);
...@@ -283,6 +284,18 @@ Name ProfilerListener::InferScriptName(Name name, SharedFunctionInfo info) { ...@@ -283,6 +284,18 @@ Name ProfilerListener::InferScriptName(Name name, SharedFunctionInfo info) {
return source_url->IsName() ? Name::cast(source_url) : name; return source_url->IsName() ? Name::cast(source_url) : name;
} }
const char* ProfilerListener::GetFunctionName(SharedFunctionInfo shared) {
DisallowHeapAllocation no_gc;
switch (naming_mode_) {
case kDebugNaming:
return GetName(shared.DebugName());
case kStandardNaming:
return GetName(shared.Name());
default:
UNREACHABLE();
}
}
void ProfilerListener::AttachDeoptInlinedFrames(Code code, void ProfilerListener::AttachDeoptInlinedFrames(Code code,
CodeDeoptEventRecord* rec) { CodeDeoptEventRecord* rec) {
int deopt_id = rec->deopt_id; int deopt_id = rec->deopt_id;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "include/v8-profiler.h"
#include "src/code-events.h" #include "src/code-events.h"
#include "src/profiler/profile-generator.h" #include "src/profiler/profile-generator.h"
...@@ -25,7 +26,8 @@ class CodeEventObserver { ...@@ -25,7 +26,8 @@ class CodeEventObserver {
class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener { class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener {
public: public:
ProfilerListener(Isolate*, CodeEventObserver*); ProfilerListener(Isolate*, CodeEventObserver*,
CpuProfilingNamingMode mode = kDebugNaming);
~ProfilerListener() override; ~ProfilerListener() override;
void CallbackEvent(Name name, Address entry_point) override; void CallbackEvent(Name name, Address entry_point) override;
...@@ -70,6 +72,8 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener { ...@@ -70,6 +72,8 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener {
void set_observer(CodeEventObserver* observer) { observer_ = observer; } void set_observer(CodeEventObserver* observer) { observer_ = observer; }
private: private:
const char* GetFunctionName(SharedFunctionInfo);
void AttachDeoptInlinedFrames(Code code, CodeDeoptEventRecord* rec); void AttachDeoptInlinedFrames(Code code, CodeDeoptEventRecord* rec);
Name InferScriptName(Name name, SharedFunctionInfo info); Name InferScriptName(Name name, SharedFunctionInfo info);
V8_INLINE void DispatchCodeEvent(const CodeEventsContainer& evt_rec) { V8_INLINE void DispatchCodeEvent(const CodeEventsContainer& evt_rec) {
...@@ -79,6 +83,7 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener { ...@@ -79,6 +83,7 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener {
Isolate* isolate_; Isolate* isolate_;
CodeEventObserver* observer_; CodeEventObserver* observer_;
StringsStorage function_and_resource_names_; StringsStorage function_and_resource_names_;
const CpuProfilingNamingMode naming_mode_;
DISALLOW_COPY_AND_ASSIGN(ProfilerListener); DISALLOW_COPY_AND_ASSIGN(ProfilerListener);
}; };
......
...@@ -53,7 +53,7 @@ void TracingCpuProfilerImpl::StartProfiling() { ...@@ -53,7 +53,7 @@ void TracingCpuProfilerImpl::StartProfiling() {
TRACE_EVENT_CATEGORY_GROUP_ENABLED( TRACE_EVENT_CATEGORY_GROUP_ENABLED(
TRACE_DISABLED_BY_DEFAULT("v8.cpu_profiler.hires"), &enabled); TRACE_DISABLED_BY_DEFAULT("v8.cpu_profiler.hires"), &enabled);
int sampling_interval_us = enabled ? 100 : 1000; int sampling_interval_us = enabled ? 100 : 1000;
profiler_.reset(new CpuProfiler(isolate_)); profiler_.reset(new CpuProfiler(isolate_, kDebugNaming));
profiler_->set_sampling_interval( profiler_->set_sampling_interval(
base::TimeDelta::FromMicroseconds(sampling_interval_us)); base::TimeDelta::FromMicroseconds(sampling_interval_us));
profiler_->StartProfiling("", true); profiler_->StartProfiling("", true);
......
...@@ -226,7 +226,7 @@ TEST(TickEvents) { ...@@ -226,7 +226,7 @@ TEST(TickEvents) {
ProfilerEventsProcessor* processor = new SamplingEventsProcessor( ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), generator, CcTest::i_isolate(), generator,
v8::base::TimeDelta::FromMicroseconds(100), true); v8::base::TimeDelta::FromMicroseconds(100), true);
CpuProfiler profiler(isolate, profiles, generator, processor); CpuProfiler profiler(isolate, kDebugNaming, profiles, generator, processor);
profiles->StartProfiling("", false); profiles->StartProfiling("", false);
processor->Start(); processor->Start();
ProfilerListener profiler_listener(isolate, processor); ProfilerListener profiler_listener(isolate, processor);
...@@ -295,7 +295,7 @@ TEST(Issue1398) { ...@@ -295,7 +295,7 @@ TEST(Issue1398) {
ProfilerEventsProcessor* processor = new SamplingEventsProcessor( ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), generator, CcTest::i_isolate(), generator,
v8::base::TimeDelta::FromMicroseconds(100), true); v8::base::TimeDelta::FromMicroseconds(100), true);
CpuProfiler profiler(isolate, profiles, generator, processor); CpuProfiler profiler(isolate, kDebugNaming, profiles, generator, processor);
profiles->StartProfiling("", false); profiles->StartProfiling("", false);
processor->Start(); processor->Start();
ProfilerListener profiler_listener(isolate, processor); ProfilerListener profiler_listener(isolate, processor);
...@@ -1153,7 +1153,7 @@ static void TickLines(bool optimize) { ...@@ -1153,7 +1153,7 @@ static void TickLines(bool optimize) {
ProfilerEventsProcessor* processor = new SamplingEventsProcessor( ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), generator, CcTest::i_isolate(), generator,
v8::base::TimeDelta::FromMicroseconds(100), true); v8::base::TimeDelta::FromMicroseconds(100), true);
CpuProfiler profiler(isolate, profiles, generator, processor); CpuProfiler profiler(isolate, kDebugNaming, profiles, generator, processor);
profiles->StartProfiling("", false); profiles->StartProfiling("", false);
// TODO(delphick): Stop using the CpuProfiler internals here: This forces // TODO(delphick): Stop using the CpuProfiler internals here: This forces
// LogCompiledFunctions so that source positions are collected everywhere. // LogCompiledFunctions so that source positions are collected everywhere.
...@@ -2857,6 +2857,78 @@ TEST(LowPrecisionSamplingStartStopPublic) { ...@@ -2857,6 +2857,78 @@ TEST(LowPrecisionSamplingStartStopPublic) {
cpu_profiler->Dispose(); cpu_profiler->Dispose();
} }
const char* naming_test_source = R"(
(function testAssignmentPropertyNamedFunction() {
let object = {};
object.propNamed = function () {
CallCollectSample();
};
object.propNamed();
})();
)";
TEST(StandardNaming) {
LocalContext env;
i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
v8::Local<v8::FunctionTemplate> func_template =
v8::FunctionTemplate::New(env->GetIsolate(), CallCollectSample);
v8::Local<v8::Function> func =
func_template->GetFunction(env.local()).ToLocalChecked();
func->SetName(v8_str("CallCollectSample"));
env->Global()->Set(env.local(), v8_str("CallCollectSample"), func).FromJust();
v8::CpuProfiler* profiler =
v8::CpuProfiler::New(env->GetIsolate(), kStandardNaming);
const auto profile_name = v8_str("");
profiler->StartProfiling(profile_name);
CompileRun(naming_test_source);
auto* profile = profiler->StopProfiling(profile_name);
auto* root = profile->GetTopDownRoot();
auto* toplevel = FindChild(root, "");
DCHECK(toplevel);
auto* prop_assignment_named_test =
GetChild(env.local(), toplevel, "testAssignmentPropertyNamedFunction");
CHECK(FindChild(prop_assignment_named_test, ""));
profiler->Dispose();
}
TEST(DebugNaming) {
LocalContext env;
i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
v8::Local<v8::FunctionTemplate> func_template =
v8::FunctionTemplate::New(env->GetIsolate(), CallCollectSample);
v8::Local<v8::Function> func =
func_template->GetFunction(env.local()).ToLocalChecked();
func->SetName(v8_str("CallCollectSample"));
env->Global()->Set(env.local(), v8_str("CallCollectSample"), func).FromJust();
v8::CpuProfiler* profiler =
v8::CpuProfiler::New(env->GetIsolate(), kDebugNaming);
const auto profile_name = v8_str("");
profiler->StartProfiling(profile_name);
CompileRun(naming_test_source);
auto* profile = profiler->StopProfiling(profile_name);
auto* root = profile->GetTopDownRoot();
auto* toplevel = FindChild(root, "");
DCHECK(toplevel);
auto* prop_assignment_named_test =
GetChild(env.local(), toplevel, "testAssignmentPropertyNamedFunction");
CHECK(FindChild(prop_assignment_named_test, "object.propNamed"));
profiler->Dispose();
}
enum class EntryCountMode { kAll, kOnlyInlined }; enum class EntryCountMode { kAll, kOnlyInlined };
// Count the number of unique source positions. // Count the number of unique source positions.
......
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