From bc9f6c607f2dd7b36b5b32c8662dd0c7823bd001 Mon Sep 17 00:00:00 2001 From: "loislo@chromium.org" Date: Mon, 1 Jul 2013 15:15:57 +0000 Subject: [PATCH] CPUProfiler: propagate scriptId to the front-end Each CpuProfileNode has resource_name string property. It cost us N * strlen(resource_name) where N is number of functions in the collected profile. We could transfer script_id instead of resource_name so it would reduce transfer size and help us to solve the problem with evals and sourceURL. BUG=none TEST=test-cpu-profiler/CollectCpuProfile R=jkummerow@chromium.org, yurys@chromium.org Review URL: https://codereview.chromium.org/17642009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15429 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8-profiler.h | 3 ++ src/api.cc | 9 ++++++ src/cpu-profiler.cc | 18 +++++++---- src/profile-generator-inl.h | 1 + src/profile-generator.cc | 3 +- src/profile-generator.h | 3 ++ test/cctest/test-profile-generator.cc | 59 +++++++++++++++++++++++++++++++++++ 7 files changed, 89 insertions(+), 7 deletions(-) diff --git a/include/v8-profiler.h b/include/v8-profiler.h index 5338fcd..8e6251a 100644 --- a/include/v8-profiler.h +++ b/include/v8-profiler.h @@ -75,6 +75,9 @@ class V8EXPORT CpuProfileNode { /** Returns function name (empty string for anonymous functions.) */ Handle GetFunctionName() const; + /** Returns id of the script where function is located. */ + int GetScriptId() const; + /** Returns resource name for script from where the function originates. */ Handle GetScriptResourceName() const; diff --git a/src/api.cc b/src/api.cc index 4a24f4b..ee80579 100644 --- a/src/api.cc +++ b/src/api.cc @@ -7326,6 +7326,15 @@ Handle CpuProfileNode::GetFunctionName() const { } +int CpuProfileNode::GetScriptId() const { + i::Isolate* isolate = i::Isolate::Current(); + IsDeadCheck(isolate, "v8::CpuProfileNode::GetScriptId"); + const i::ProfileNode* node = reinterpret_cast(this); + const i::CodeEntry* entry = node->entry(); + return entry->script_id(); +} + + Handle CpuProfileNode::GetScriptResourceName() const { i::Isolate* isolate = i::Isolate::Current(); IsDeadCheck(isolate, "v8::CpuProfileNode::GetScriptResourceName"); diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc index 270da8f..55d8121 100644 --- a/src/cpu-profiler.cc +++ b/src/cpu-profiler.cc @@ -255,9 +255,12 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; rec->start = code->address(); rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name)); - rec->entry->set_no_frame_ranges(info ? - info->ReleaseNoFrameRanges() : - NULL); + if (info) { + rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges()); + } + ASSERT(Script::cast(shared->script())); + Script* script = Script::cast(shared->script()); + rec->entry->set_script_id(script->id()->value()); rec->size = code->ExecutableSize(); rec->shared = shared->address(); processor_->Enqueue(evt_rec); @@ -280,9 +283,12 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, CodeEntry::kEmptyNamePrefix, profiles_->GetName(source), line); - rec->entry->set_no_frame_ranges(info ? - info->ReleaseNoFrameRanges() : - NULL); + if (info) { + rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges()); + } + ASSERT(Script::cast(shared->script())); + Script* script = Script::cast(shared->script()); + rec->entry->set_script_id(script->id()->value()); rec->size = code->ExecutableSize(); rec->shared = shared->address(); processor_->Enqueue(evt_rec); diff --git a/src/profile-generator-inl.h b/src/profile-generator-inl.h index 115e813..20c1aec 100644 --- a/src/profile-generator-inl.h +++ b/src/profile-generator-inl.h @@ -56,6 +56,7 @@ CodeEntry::CodeEntry(Logger::LogEventsAndTags tag, resource_name_(resource_name), line_number_(line_number), shared_id_(0), + script_id_(v8::Script::kNoScriptId), security_token_id_(security_token_id), no_frame_ranges_(NULL) { } diff --git a/src/profile-generator.cc b/src/profile-generator.cc index 1354487..aeb80a3 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -273,12 +273,13 @@ double ProfileNode::GetTotalMillis() const { void ProfileNode::Print(int indent) { - OS::Print("%5u %5u %*c %s%s [%d] #%d", + OS::Print("%5u %5u %*c %s%s [%d] #%d %d", total_ticks_, self_ticks_, indent, ' ', entry_->name_prefix(), entry_->name(), entry_->security_token_id(), + entry_->script_id(), id()); if (entry_->resource_name()[0] != '\0') OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number()); diff --git a/src/profile-generator.h b/src/profile-generator.h index 2783a08..411cbdb 100644 --- a/src/profile-generator.h +++ b/src/profile-generator.h @@ -111,6 +111,8 @@ class CodeEntry { INLINE(const char* resource_name() const) { return resource_name_; } INLINE(int line_number() const) { return line_number_; } INLINE(void set_shared_id(int shared_id)) { shared_id_ = shared_id; } + INLINE(int script_id() const) { return script_id_; } + INLINE(void set_script_id(int script_id)) { script_id_ = script_id; } INLINE(int security_token_id() const) { return security_token_id_; } INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag)); @@ -138,6 +140,7 @@ class CodeEntry { const char* resource_name_; int line_number_; int shared_id_; + int script_id_; int security_token_id_; List* no_frame_ranges_; diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc index e919789..dfcc75c 100644 --- a/test/cctest/test-profile-generator.cc +++ b/test/cctest/test-profile-generator.cc @@ -905,3 +905,62 @@ TEST(Issue51919) { for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i) i::DeleteArray(titles[i]); } + + +static const v8::CpuProfileNode* PickChild(const v8::CpuProfileNode* parent, + const char* name) { + for (int i = 0; i < parent->GetChildrenCount(); ++i) { + const v8::CpuProfileNode* child = parent->GetChild(i); + v8::String::AsciiValue function_name(child->GetFunctionName()); + if (strcmp(*function_name, name) == 0) return child; + } + return NULL; +} + + +TEST(ProfileNodeScriptId) { + // This test does not pass with inlining enabled since inlined functions + // don't appear in the stack trace. + i::FLAG_use_inlining = false; + + const char* extensions[] = { "v8/profiler" }; + v8::ExtensionConfiguration config(1, extensions); + LocalContext env(&config); + v8::HandleScope hs(env->GetIsolate()); + + v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler(); + CHECK_EQ(0, profiler->GetProfileCount()); + v8::Handle script_a = v8::Script::Compile(v8::String::New( + "function a() { startProfiling(); }\n")); + script_a->Run(); + v8::Handle script_b = v8::Script::Compile(v8::String::New( + "function b() { a(); }\n" + "b();\n" + "stopProfiling();\n")); + script_b->Run(); + CHECK_EQ(1, profiler->GetProfileCount()); + const v8::CpuProfile* profile = profiler->GetCpuProfile(0); + const v8::CpuProfileNode* current = profile->GetTopDownRoot(); + reinterpret_cast( + const_cast(current))->Print(0); + // The tree should look like this: + // (root) + // (anonymous function) + // b + // a + // There can also be: + // startProfiling + // if the sampler managed to get a tick. + current = PickChild(current, i::ProfileGenerator::kAnonymousFunctionName); + CHECK_NE(NULL, const_cast(current)); + + current = PickChild(current, "b"); + CHECK_NE(NULL, const_cast(current)); + CHECK_EQ(script_b->GetId(), current->GetScriptId()); + + current = PickChild(current, "a"); + CHECK_NE(NULL, const_cast(current)); + CHECK_EQ(script_a->GetId(), current->GetScriptId()); +} + + -- 2.7.4