Commit 344d836d authored by yurys@chromium.org's avatar yurys@chromium.org

Add column getter to CpuProfileNode

CpuProfileNode currently exposes only line number which is not enough for the cases when there is more than one function on the same line. This change exposes column number on CpuProfileNode.

BUG=302537
R=jkummerow@chromium.org, loislo@chromium.org

Review URL: https://codereview.chromium.org/25541003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17142 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f9fbe4fc
......@@ -57,6 +57,12 @@ class V8_EXPORT CpuProfileNode {
*/
int GetLineNumber() const;
/**
* Returns 1-based number of the column where the function originates.
* kNoColumnNumberInfo if no column number information is available.
*/
int GetColumnNumber() const;
/** Returns bailout reason for the function
* if the optimization was disabled for it.
*/
......@@ -80,6 +86,7 @@ class V8_EXPORT CpuProfileNode {
const CpuProfileNode* GetChild(int index) const;
static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
};
......
......@@ -6928,6 +6928,12 @@ int CpuProfileNode::GetLineNumber() const {
}
int CpuProfileNode::GetColumnNumber() const {
return reinterpret_cast<const i::ProfileNode*>(this)->
entry()->column_number();
}
const char* CpuProfileNode::GetBailoutReason() const {
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
return node->entry()->bailout_reason();
......
......@@ -261,7 +261,7 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
CompilationInfo* info,
Name* source, int line) {
Name* source, int line, int column) {
if (FilterOutCodeCreateEvent(tag)) return;
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
......@@ -271,7 +271,8 @@ void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
profiles_->GetFunctionName(shared->DebugName()),
CodeEntry::kEmptyNamePrefix,
profiles_->GetName(source),
line);
line,
column);
if (info) {
rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
}
......
......@@ -238,7 +238,7 @@ class CpuProfiler : public CodeEventListener {
Code* code,
SharedFunctionInfo* shared,
CompilationInfo* info,
Name* source, int line);
Name* source, int line, int column);
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, int args_count);
virtual void CodeMovingGCEvent() {}
......
......@@ -212,7 +212,7 @@ void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
CompilationInfo* info,
Name* source, int line) {
Name* source, int line, int column) {
name_buffer_->Init(tag);
name_buffer_->AppendBytes(ComputeMarker(code));
name_buffer_->AppendString(shared->DebugName());
......@@ -1232,10 +1232,11 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
SharedFunctionInfo* shared,
CompilationInfo* info,
Name* source, int line, int column) {
PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, source, line));
PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, source, line, column));
if (!is_logging_code_events()) return;
CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, source, line));
CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, source, line,
column));
if (!FLAG_log_code || !log_->IsEnabled()) return;
Log::MessageBuilder msg(log_);
......
......@@ -471,7 +471,7 @@ class CodeEventListener {
SharedFunctionInfo* shared,
CompilationInfo* info,
Name* source,
int line) = 0;
int line, int column) = 0;
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
int args_count) = 0;
......@@ -510,7 +510,7 @@ class CodeEventLogger : public CodeEventListener {
SharedFunctionInfo* shared,
CompilationInfo* info,
Name* source,
int line);
int line, int column);
virtual void RegExpCodeCreateEvent(Code* code, String* source);
virtual void CallbackEvent(Name* name, Address entry_point) { }
......
......@@ -47,13 +47,15 @@ CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
const char* name,
const char* name_prefix,
const char* resource_name,
int line_number)
int line_number,
int column_number)
: tag_(tag),
builtin_id_(Builtins::builtin_count),
name_prefix_(name_prefix),
name_(name),
resource_name_(resource_name),
line_number_(line_number),
column_number_(column_number),
shared_id_(0),
script_id_(v8::Script::kNoScriptId),
no_frame_ranges_(NULL),
......
......@@ -546,12 +546,14 @@ CodeEntry* CpuProfilesCollection::NewCodeEntry(
const char* name,
const char* name_prefix,
const char* resource_name,
int line_number) {
int line_number,
int column_number) {
CodeEntry* code_entry = new CodeEntry(tag,
name,
name_prefix,
resource_name,
line_number);
line_number,
column_number);
code_entries_.Add(code_entry);
return code_entry;
}
......
......@@ -77,7 +77,9 @@ class CodeEntry {
const char* name,
const char* name_prefix = CodeEntry::kEmptyNamePrefix,
const char* resource_name = CodeEntry::kEmptyResourceName,
int line_number = v8::CpuProfileNode::kNoLineNumberInfo));
int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
int column_number =
v8::CpuProfileNode::kNoColumnNumberInfo));
~CodeEntry();
INLINE(bool is_js_function() const) { return is_js_function_tag(tag_); }
......@@ -86,6 +88,7 @@ class CodeEntry {
INLINE(const char* name() const) { return name_; }
INLINE(const char* resource_name() const) { return resource_name_; }
INLINE(int line_number() const) { return line_number_; }
int column_number() const { return column_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; }
......@@ -119,6 +122,7 @@ class CodeEntry {
const char* name_;
const char* resource_name_;
int line_number_;
int column_number_;
int shared_id_;
int script_id_;
List<OffsetRange>* no_frame_ranges_;
......@@ -304,7 +308,8 @@ class CpuProfilesCollection {
const char* name,
const char* name_prefix = CodeEntry::kEmptyNamePrefix,
const char* resource_name = CodeEntry::kEmptyResourceName,
int line_number = v8::CpuProfileNode::kNoLineNumberInfo);
int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
int column_number = v8::CpuProfileNode::kNoColumnNumberInfo);
// Called from profile generator thread.
void AddPathToCurrentProfiles(const Vector<CodeEntry*>& path);
......
......@@ -1389,3 +1389,56 @@ TEST(IdleTime) {
cpu_profiler->DeleteAllCpuProfiles();
}
static void CheckFunctionDetails(const v8::CpuProfileNode* node,
const char* name, const char* script_name, int script_id,
int line, int column) {
CHECK_EQ(v8::String::New(name), node->GetFunctionName());
CHECK_EQ(v8::String::New(script_name), node->GetScriptResourceName());
CHECK_EQ(script_id, node->GetScriptId());
CHECK_EQ(line, node->GetLineNumber());
CHECK_EQ(column, node->GetColumnNumber());
}
TEST(FunctionDetails) {
const char* extensions[] = { "v8/profiler" };
v8::ExtensionConfiguration config(1, extensions);
LocalContext env(&config);
v8::HandleScope handleScope(env->GetIsolate());
v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler();
CHECK_EQ(0, profiler->GetProfileCount());
v8::Handle<v8::Script> script_a = v8::Script::Compile(v8::String::New(
" function foo\n() { try { bar(); } catch(e) {} }\n"
" function bar() { startProfiling(); }\n"), v8::String::New("script_a"));
script_a->Run();
v8::Handle<v8::Script> script_b = v8::Script::Compile(v8::String::New(
"\n\n function baz() { try { foo(); } catch(e) {} }\n"
"\n\nbaz();\n"
"stopProfiling();\n"), v8::String::New("script_b"));
script_b->Run();
CHECK_EQ(1, profiler->GetProfileCount());
const v8::CpuProfile* profile = profiler->GetCpuProfile(0);
const v8::CpuProfileNode* current = profile->GetTopDownRoot();
reinterpret_cast<ProfileNode*>(
const_cast<v8::CpuProfileNode*>(current))->Print(0);
// The tree should look like this:
// 0 (root) 0 #1
// 0 (anonymous function) 19 #2 no reason script_b:1
// 0 baz 19 #3 TryCatchStatement script_b:3
// 0 foo 18 #4 TryCatchStatement script_a:2
// 1 bar 18 #5 no reason script_a:3
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
const v8::CpuProfileNode* script = GetChild(root,
ProfileGenerator::kAnonymousFunctionName);
CheckFunctionDetails(script, ProfileGenerator::kAnonymousFunctionName,
"script_b", script_b->GetId(), 1, 1);
const v8::CpuProfileNode* baz = GetChild(script, "baz");
CheckFunctionDetails(baz, "baz", "script_b", script_b->GetId(), 3, 16);
const v8::CpuProfileNode* foo = GetChild(baz, "foo");
CheckFunctionDetails(foo, "foo", "script_a", script_a->GetId(), 2, 1);
const v8::CpuProfileNode* bar = GetChild(foo, "bar");
CheckFunctionDetails(bar, "bar", "script_a", script_a->GetId(), 3, 14);
}
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