Revision: 4357
Author: [email protected]
Date: Wed Apr 7 07:18:26 2010
Log: C++ profiles processor: align browser mode with the old
implementation, sample VM state.
In browser (DevTools) mode, only non-native JS code and callbacks are
reported.
Also, added "(garbage collector)" entry which accumulates samples count in
GC state.
Trying to display "(compiler)" and "(external)" only brings confusion,
because it ends up in displaying scripts code under "(compiler)" node, and
DOM
event handlers under "(external)" node, which looks weird.
Review URL: http://codereview.chromium.org/1523015
http://code.google.com/p/v8/source/detail?r=4357
Modified:
/branches/bleeding_edge/src/compiler.cc
/branches/bleeding_edge/src/cpu-profiler-inl.h
/branches/bleeding_edge/src/cpu-profiler.cc
/branches/bleeding_edge/src/cpu-profiler.h
/branches/bleeding_edge/src/globals.h
/branches/bleeding_edge/src/log-inl.h
/branches/bleeding_edge/src/log.cc
/branches/bleeding_edge/src/log.h
/branches/bleeding_edge/src/platform-linux.cc
/branches/bleeding_edge/src/platform-macos.cc
/branches/bleeding_edge/src/platform-win32.cc
/branches/bleeding_edge/src/platform.h
/branches/bleeding_edge/src/profile-generator-inl.h
/branches/bleeding_edge/src/profile-generator.cc
/branches/bleeding_edge/src/profile-generator.h
/branches/bleeding_edge/test/cctest/test-cpu-profiler.cc
=======================================
--- /branches/bleeding_edge/src/compiler.cc Tue Apr 6 03:36:38 2010
+++ /branches/bleeding_edge/src/compiler.cc Wed Apr 7 07:18:26 2010
@@ -217,14 +217,18 @@
}
if (script->name()->IsString()) {
- PROFILE(CodeCreateEvent(is_eval ? Logger::EVAL_TAG :
Logger::SCRIPT_TAG,
- *code, String::cast(script->name())));
+ PROFILE(CodeCreateEvent(
+ is_eval ? Logger::EVAL_TAG :
+ Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
+ *code, String::cast(script->name())));
OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
code->instruction_start(),
code->instruction_size()));
} else {
- PROFILE(CodeCreateEvent(is_eval ? Logger::EVAL_TAG :
Logger::SCRIPT_TAG,
- *code, ""));
+ PROFILE(CodeCreateEvent(
+ is_eval ? Logger::EVAL_TAG :
+ Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
+ *code, ""));
OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
code->instruction_start(),
code->instruction_size()));
@@ -592,7 +596,8 @@
if (script->name()->IsString()) {
int line_num = GetScriptLineNumber(script, start_position) + 1;
USE(line_num);
- PROFILE(CodeCreateEvent(tag, *code, *func_name,
+ PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
+ *code, *func_name,
String::cast(script->name()), line_num));
OPROFILE(CreateNativeCodeRegion(*func_name,
String::cast(script->name()),
@@ -600,7 +605,8 @@
code->instruction_start(),
code->instruction_size()));
} else {
- PROFILE(CodeCreateEvent(tag, *code, *func_name));
+ PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
+ *code, *func_name));
OPROFILE(CreateNativeCodeRegion(*func_name,
code->instruction_start(),
code->instruction_size()));
=======================================
--- /branches/bleeding_edge/src/cpu-profiler-inl.h Tue Apr 6 03:36:38 2010
+++ /branches/bleeding_edge/src/cpu-profiler-inl.h Wed Apr 7 07:18:26 2010
@@ -64,6 +64,20 @@
evt->order = enqueue_order_; // No increment!
return &evt->sample;
}
+
+
+bool ProfilerEventsProcessor::FilterOutCodeCreateEvent(
+ Logger::LogEventsAndTags tag) {
+ // In browser mode, leave only callbacks and non-native JS entries.
+ // We filter out regular expressions as currently we can't tell
+ // whether they origin from native scripts, so let's not confise people
by
+ // showing them weird regexes they didn't wrote.
+ return FLAG_prof_browser_mode
+ && (tag != Logger::CALLBACK_TAG
+ && tag != Logger::FUNCTION_TAG
+ && tag != Logger::LAZY_COMPILE_TAG
+ && tag != Logger::SCRIPT_TAG);
+}
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/cpu-profiler.cc Tue Apr 6 07:54:20 2010
+++ /branches/bleeding_edge/src/cpu-profiler.cc Wed Apr 7 07:18:26 2010
@@ -57,6 +57,7 @@
const char* prefix,
String* name,
Address start) {
+ if (FilterOutCodeCreateEvent(tag)) return;
CodeEventsContainer evt_rec;
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->type = CodeEventRecord::CODE_CREATION;
@@ -74,6 +75,7 @@
int line_number,
Address start,
unsigned size) {
+ if (FilterOutCodeCreateEvent(tag)) return;
CodeEventsContainer evt_rec;
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->type = CodeEventRecord::CODE_CREATION;
@@ -89,6 +91,7 @@
const char* name,
Address start,
unsigned size) {
+ if (FilterOutCodeCreateEvent(tag)) return;
CodeEventsContainer evt_rec;
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->type = CodeEventRecord::CODE_CREATION;
@@ -104,6 +107,7 @@
int args_count,
Address start,
unsigned size) {
+ if (FilterOutCodeCreateEvent(tag)) return;
CodeEventsContainer evt_rec;
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->type = CodeEventRecord::CODE_CREATION;
@@ -164,6 +168,7 @@
String* name,
Address start,
unsigned size) {
+ if (FilterOutCodeCreateEvent(tag)) return;
CodeEventsContainer evt_rec;
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->type = CodeEventRecord::CODE_CREATION;
=======================================
--- /branches/bleeding_edge/src/cpu-profiler.h Tue Apr 6 07:54:20 2010
+++ /branches/bleeding_edge/src/cpu-profiler.h Wed Apr 7 07:18:26 2010
@@ -104,9 +104,10 @@
class TickSampleEventRecord BASE_EMBEDDED {
public:
// In memory, the first machine word of a TickSampleEventRecord will be
the
- // first entry of TickSample, that is -- a program counter field.
+ // first entry of TickSample, that is -- the VM state field.
// TickSample is put first, because 'order' can become equal to
- // SamplingCircularQueue::kClear, while program counter can't.
+ // SamplingCircularQueue::kClear, while VM state can't, see
+ // the definition of 'enum StateTag'.
TickSample sample;
unsigned order;
@@ -172,6 +173,8 @@
bool ProcessCodeEvent(unsigned* dequeue_order);
bool ProcessTicks(unsigned dequeue_order);
+ INLINE(static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags
tag));
+
ProfileGenerator* generator_;
bool running_;
CircularQueue<CodeEventsContainer> events_buffer_;
@@ -236,8 +239,7 @@
static void SetterCallbackEvent(String* name, Address entry_point);
static INLINE(bool is_profiling()) {
- ASSERT(singleton_ != NULL);
- return singleton_->processor_ != NULL;
+ return singleton_ != NULL && singleton_->processor_ != NULL;
}
private:
=======================================
--- /branches/bleeding_edge/src/globals.h Tue Apr 6 02:27:09 2010
+++ /branches/bleeding_edge/src/globals.h Wed Apr 7 07:18:26 2010
@@ -471,6 +471,11 @@
V(EXTERNAL)
enum StateTag {
+#ifdef ENABLE_CPP_PROFILES_PROCESSOR
+ // This is to ensure that VM state field value of TickSample
+ // never gets equal to SamplingCircularQueue::kClear.
+ NULL_STATE = 0,
+#endif
#define DEF_STATE_TAG(name) name,
STATE_TAG_LIST(DEF_STATE_TAG)
#undef DEF_STATE_TAG
=======================================
--- /branches/bleeding_edge/src/log-inl.h Mon Nov 23 06:43:00 2009
+++ /branches/bleeding_edge/src/log-inl.h Wed Apr 7 07:18:26 2010
@@ -29,6 +29,7 @@
#define V8_LOG_INL_H_
#include "log.h"
+#include "cpu-profiler.h"
namespace v8 {
namespace internal {
@@ -55,10 +56,13 @@
}
}
-VMState::VMState(StateTag state) : disabled_(true),
external_callback_(NULL) {
- if (!Logger::is_logging()) {
+VMState::VMState(StateTag state)
+ : disabled_(true),
+ state_(OTHER),
+ external_callback_(NULL) {
+ if (!Logger::is_logging() && !CpuProfiler::is_profiling()) {
return;
- }
+}
disabled_ = false;
#if !defined(ENABLE_HEAP_PROTECTION)
@@ -118,6 +122,26 @@
}
#endif
}
+
+Logger::LogEventsAndTags Logger::ToNativeByScript(Logger::LogEventsAndTags
tag,
+ Script* script) {
+#ifdef ENABLE_CPP_PROFILES_PROCESSOR
+ if ((tag == FUNCTION_TAG || tag == LAZY_COMPILE_TAG || tag == SCRIPT_TAG)
+ && script->type()->value() == Script::TYPE_NATIVE) {
+ switch (tag) {
+ case FUNCTION_TAG: return NATIVE_FUNCTION_TAG;
+ case LAZY_COMPILE_TAG: return NATIVE_LAZY_COMPILE_TAG;
+ case SCRIPT_TAG: return NATIVE_SCRIPT_TAG;
+ default: return tag;
+ }
+ } else {
+ return tag;
+ }
+#else
+ return tag;
+#endif
+}
+
#endif
=======================================
--- /branches/bleeding_edge/src/log.cc Tue Apr 6 03:36:38 2010
+++ /branches/bleeding_edge/src/log.cc Wed Apr 7 07:18:26 2010
@@ -1337,17 +1337,20 @@
Handle<String> script_name(String::cast(script->name()));
int line_num = GetScriptLineNumber(script,
shared->start_position());
if (line_num > 0) {
- PROFILE(CodeCreateEvent(Logger::LAZY_COMPILE_TAG,
- shared->code(), *func_name,
- *script_name, line_num + 1));
+ PROFILE(CodeCreateEvent(
+ Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
+ shared->code(), *func_name,
+ *script_name, line_num + 1));
} else {
- // Can't distinguish enum and script here, so always use Script.
- PROFILE(CodeCreateEvent(Logger::SCRIPT_TAG,
- shared->code(), *script_name));
+ // Can't distinguish eval and script here, so always use Script.
+ PROFILE(CodeCreateEvent(
+ Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
+ shared->code(), *script_name));
}
} else {
PROFILE(CodeCreateEvent(
- Logger::LAZY_COMPILE_TAG, shared->code(), *func_name));
+ Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
+ shared->code(), *func_name));
}
} else if (shared->IsApiFunction()) {
// API function.
=======================================
--- /branches/bleeding_edge/src/log.h Tue Apr 6 03:36:38 2010
+++ /branches/bleeding_edge/src/log.h Wed Apr 7 07:18:26 2010
@@ -148,6 +148,11 @@
enum LogEventsAndTags {
LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM)
NUMBER_OF_LOG_EVENTS
+#ifdef ENABLE_CPP_PROFILES_PROCESSOR
+ , NATIVE_FUNCTION_TAG
+ , NATIVE_LAZY_COMPILE_TAG
+ , NATIVE_SCRIPT_TAG
+#endif
};
#undef DECLARE_ENUM
@@ -287,6 +292,9 @@
// Used for logging stubs found in the snapshot.
static void LogCodeObjects();
+ // Converts tag to a corresponding NATIVE_... if the script is native.
+ INLINE(static LogEventsAndTags ToNativeByScript(LogEventsAndTags,
Script*));
+
private:
// Profiler's sampling interval (in milliseconds).
=======================================
--- /branches/bleeding_edge/src/platform-linux.cc Tue Apr 6 07:54:20 2010
+++ /branches/bleeding_edge/src/platform-linux.cc Wed Apr 7 07:18:26 2010
@@ -728,52 +728,47 @@
if (active_sampler_ == NULL) return;
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
- if (Logger::state() == GC || !IsVmThread()) return;
-
- TickSample* sample = NULL;
+ TickSample* sample = CpuProfiler::TickSampleEvent();
+ if (sample == NULL) return;
+ sample->pc = NULL; // Impossible value if sampling succeeds.
+ sample->frames_count = 0;
#else
TickSample sample_obj;
TickSample* sample = &sample_obj;
+#endif
// We always sample the VM state.
sample->state = Logger::state();
-#endif
-
// If profiling, we extract the current pc and sp.
if (active_sampler_->IsProfiling()) {
// Extracting the sample from the context is extremely machine
dependent.
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
mcontext_t& mcontext = ucontext->uc_mcontext;
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
- sample = CpuProfiler::TickSampleEvent();
-#endif
- if (sample != NULL) {
#if V8_HOST_ARCH_IA32
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
+ sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
+ sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
+ sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
#elif V8_HOST_ARCH_X64
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
+ sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
+ sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
+ sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
#elif V8_HOST_ARCH_ARM
// An undefined macro evaluates to 0, so this applies to Android's Bionic
also.
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
+ sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
+ sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
+ sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
#else
- sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
- sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
- sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
+ sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
+ sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
+ sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
#endif
#elif V8_HOST_ARCH_MIPS
// Implement this on MIPS.
- UNIMPLEMENTED();
+ UNIMPLEMENTED();
#endif
- if (IsVmThread()) {
- active_sampler_->SampleStack(sample);
- }
+ if (IsVmThread()) {
+ active_sampler_->SampleStack(sample);
}
}
#ifndef ENABLE_CPP_PROFILES_PROCESSOR
=======================================
--- /branches/bleeding_edge/src/platform-macos.cc Tue Apr 6 03:36:38 2010
+++ /branches/bleeding_edge/src/platform-macos.cc Wed Apr 7 07:18:26 2010
@@ -547,17 +547,17 @@
// Loop until the sampler is disengaged, keeping the specified samling
freq.
for ( ; sampler_->IsActive(); OS::Sleep(sampler_->interval_)) {
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
- if (Logger::state() == GC) continue;
-
- TickSample* sample = NULL;
+ TickSample* sample = CpuProfiler::TickSampleEvent();
+ if (sample == NULL) continue;
+ sample->pc = NULL; // Impossible value if sampling succeeds.
+ sample->frames_count = 0;
#else
TickSample sample_obj;
TickSample* sample = &sample_obj;
+#endif // ENABLE_CPP_PROFILES_PROCESSOR
// We always sample the VM state.
sample->state = Logger::state();
-#endif // ENABLE_CPP_PROFILES_PROCESSOR
-
// If profiling, we record the pc and sp of the profiled thread.
if (sampler_->IsProfiling()
&& KERN_SUCCESS == thread_suspend(profiled_thread_)) {
@@ -587,15 +587,10 @@
flavor,
reinterpret_cast<natural_t*>(&state),
&count) == KERN_SUCCESS) {
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
- sample = CpuProfiler::TickSampleEvent();
-#endif
- if (sample != NULL) {
- sample->pc =
reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
- sample->sp =
reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
- sample->fp =
reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
- sampler_->SampleStack(sample);
- }
+ sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
+ sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
+ sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
+ sampler_->SampleStack(sample);
}
thread_resume(profiled_thread_);
}
=======================================
--- /branches/bleeding_edge/src/platform-win32.cc Tue Apr 6 03:36:38 2010
+++ /branches/bleeding_edge/src/platform-win32.cc Wed Apr 7 07:18:26 2010
@@ -1806,37 +1806,32 @@
// Loop until the sampler is disengaged, keeping the specified samling
freq.
for ( ; sampler_->IsActive(); Sleep(sampler_->interval_)) {
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
- if (Logger::state() == GC) continue;
-
- TickSample* sample = NULL;
+ TickSample* sample = CpuProfiler::TickSampleEvent();
+ if (sample == NULL) continue;
+ sample->pc = NULL; // Impossible value if sampling succeeds.
+ sample->frames_count = 0;
#else
TickSample sample_obj;
TickSample* sample = &sample_obj;
+#endif // ENABLE_CPP_PROFILES_PROCESSOR
// We always sample the VM state.
sample->state = Logger::state();
-#endif // ENABLE_CPP_PROFILES_PROCESSOR
-
// If profiling, we record the pc and sp of the profiled thread.
if (sampler_->IsProfiling()
&& SuspendThread(profiled_thread_) != (DWORD)-1) {
context.ContextFlags = CONTEXT_FULL;
if (GetThreadContext(profiled_thread_, &context) != 0) {
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
- sample = CpuProfiler::TickSampleEvent();
-#endif
- if (sample != NULL) {
#if V8_HOST_ARCH_X64
- sample->pc = reinterpret_cast<Address>(context.Rip);
- sample->sp = reinterpret_cast<Address>(context.Rsp);
- sample->fp = reinterpret_cast<Address>(context.Rbp);
+ sample->pc = reinterpret_cast<Address>(context.Rip);
+ sample->sp = reinterpret_cast<Address>(context.Rsp);
+ sample->fp = reinterpret_cast<Address>(context.Rbp);
#else
- sample->pc = reinterpret_cast<Address>(context.Eip);
- sample->sp = reinterpret_cast<Address>(context.Esp);
- sample->fp = reinterpret_cast<Address>(context.Ebp);
+ sample->pc = reinterpret_cast<Address>(context.Eip);
+ sample->sp = reinterpret_cast<Address>(context.Esp);
+ sample->fp = reinterpret_cast<Address>(context.Ebp);
#endif
- sampler_->SampleStack(sample);
- }
+ sampler_->SampleStack(sample);
}
ResumeThread(profiled_thread_);
}
=======================================
--- /branches/bleeding_edge/src/platform.h Tue Apr 6 03:36:38 2010
+++ /branches/bleeding_edge/src/platform.h Wed Apr 7 07:18:26 2010
@@ -516,17 +516,17 @@
class TickSample {
public:
TickSample()
- : pc(NULL),
+ : state(OTHER),
+ pc(NULL),
sp(NULL),
fp(NULL),
function(NULL),
- state(OTHER),
frames_count(0) {}
+ StateTag state; // The state of the VM.
Address pc; // Instruction pointer.
Address sp; // Stack pointer.
Address fp; // Frame pointer.
Address function; // The last called JS function.
- StateTag state; // The state of the VM.
static const int kMaxFramesCount = 64;
Address stack[kMaxFramesCount]; // Call stack.
int frames_count; // Number of captured frames.
=======================================
--- /branches/bleeding_edge/src/profile-generator-inl.h Tue Apr 6 07:54:20
2010
+++ /branches/bleeding_edge/src/profile-generator-inl.h Wed Apr 7 07:18:26
2010
@@ -49,10 +49,13 @@
}
-bool CodeEntry::is_js_function() const {
- return tag_ == Logger::FUNCTION_TAG
- || tag_ == Logger::LAZY_COMPILE_TAG
- || tag_ == Logger::SCRIPT_TAG;
+bool CodeEntry::is_js_function_tag(Logger::LogEventsAndTags tag) {
+ return tag == Logger::FUNCTION_TAG
+ || tag == Logger::LAZY_COMPILE_TAG
+ || tag == Logger::SCRIPT_TAG
+ || tag == Logger::NATIVE_FUNCTION_TAG
+ || tag == Logger::NATIVE_LAZY_COMPILE_TAG
+ || tag == Logger::NATIVE_SCRIPT_TAG;
}
@@ -85,6 +88,33 @@
// so no locking is needed here.
return current_profiles_.length() == 1;
}
+
+
+const char* CpuProfilesCollection::GetFunctionName(String* name) {
+ return GetFunctionName(GetName(name));
+}
+
+
+const char* CpuProfilesCollection::GetFunctionName(const char* name) {
+ return strlen(name) > 0 ? name :
ProfileGenerator::kAnonymousFunctionName;
+}
+
+
+CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
+ switch (tag) {
+ case GC:
+ return gc_entry_;
+ case JS:
+ case COMPILER:
+ // DOM events handlers are reported as OTHER / EXTERNAL entries.
+ // To avoid confusing people, let's put all these entries into
+ // one bucket.
+ case OTHER:
+ case EXTERNAL:
+ return program_entry_;
+ default: return NULL;
+ }
+}
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Tue Apr 6 07:54:20
2010
+++ /branches/bleeding_edge/src/profile-generator.cc Wed Apr 7 07:18:26
2010
@@ -383,7 +383,7 @@
const char* name) {
CodeEntry* entry = new CodeEntry(tag,
CodeEntry::kEmptyNamePrefix,
- name,
+ GetFunctionName(name),
"",
v8::CpuProfileNode::kNoLineNumberInfo);
code_entries_.Add(entry);
@@ -414,13 +414,6 @@
code_entries_.Add(entry);
return entry;
}
-
-
-const char* CpuProfilesCollection::GetFunctionName(String* name) {
- const char* maybe_empty_name = GetName(name);
- return strlen(maybe_empty_name) > 0 ?
- maybe_empty_name : "(anonymous function)";
-}
const char* CpuProfilesCollection::GetName(String* name) {
@@ -473,44 +466,56 @@
}
+const char* ProfileGenerator::kAnonymousFunctionName = "(anonymous
function)";
+const char* ProfileGenerator::kProgramEntryName = "(program)";
+const char* ProfileGenerator::kGarbageCollectorEntryName =
+ "(garbage collector)";
+
ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
: profiles_(profiles),
program_entry_(
- profiles->NewCodeEntry(Logger::FUNCTION_TAG, "(program)")) {
+ profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)),
+ gc_entry_(
+ profiles->NewCodeEntry(Logger::BUILTIN_TAG,
+ kGarbageCollectorEntryName)) {
}
void ProfileGenerator::RecordTickSample(const TickSample& sample) {
- // Allocate space for stack frames + pc + function + (program).
+ // Allocate space for stack frames + pc + function + vm-state.
ScopedVector<CodeEntry*> entries(sample.frames_count + 3);
+ // As actual number of decoded code entries may vary, initialize
+ // entries vector with NULL values.
CodeEntry** entry = entries.start();
- *entry++ = code_map_.FindEntry(sample.pc);
-
- if (sample.function != NULL) {
- *entry = code_map_.FindEntry(sample.function);
- if (*entry != NULL && !(*entry)->is_js_function()) {
- *entry = NULL;
- } else {
- CodeEntry* pc_entry = *entries.start();
- if (pc_entry == NULL || pc_entry->is_js_function())
+ memset(entry, 0, entries.length() * sizeof(*entry));
+ if (sample.pc != NULL) {
+ *entry++ = code_map_.FindEntry(sample.pc);
+
+ if (sample.function != NULL) {
+ *entry = code_map_.FindEntry(sample.function);
+ if (*entry != NULL && !(*entry)->is_js_function()) {
*entry = NULL;
- }
- entry++;
- } else {
- *entry++ = NULL;
- }
-
- for (const Address *stack_pos = sample.stack,
- *stack_end = stack_pos + sample.frames_count;
- stack_pos != stack_end;
- ++stack_pos) {
- *entry++ = code_map_.FindEntry(*stack_pos);
+ } else {
+ CodeEntry* pc_entry = *entries.start();
+ if (pc_entry == NULL || pc_entry->is_js_function())
+ *entry = NULL;
+ }
+ entry++;
+ }
+
+ for (const Address *stack_pos = sample.stack,
+ *stack_end = stack_pos + sample.frames_count;
+ stack_pos != stack_end;
+ ++stack_pos) {
+ *entry++ = code_map_.FindEntry(*stack_pos);
+ }
}
- // WebKit CPU profiles visualization requires "(program)" to be the
- // topmost entry.
- *entry++ = FLAG_prof_browser_mode ? program_entry_ : NULL;
+ if (FLAG_prof_browser_mode) {
+ // Put VM state as the topmost entry.
+ *entry++ = EntryForVMState(sample.state);
+ }
profiles_->AddPathToCurrentProfiles(entries);
}
=======================================
--- /branches/bleeding_edge/src/profile-generator.h Tue Apr 6 07:54:20 2010
+++ /branches/bleeding_edge/src/profile-generator.h Wed Apr 7 07:18:26 2010
@@ -44,13 +44,15 @@
const char* resource_name,
int line_number));
- INLINE(bool is_js_function() const);
+ INLINE(bool is_js_function() const) { return is_js_function_tag(tag_); }
INLINE(const char* name_prefix() const) { return name_prefix_; }
INLINE(bool has_name_prefix() const) { return name_prefix_[0] != '\0'; }
INLINE(const char* name() const) { return name_; }
INLINE(const char* resource_name() const) { return resource_name_; }
INLINE(int line_number() const) { return line_number_; }
INLINE(unsigned call_uid() const) { return call_uid_; }
+
+ INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag));
static const char* kEmptyNamePrefix;
@@ -223,7 +225,8 @@
void AddPathToCurrentProfiles(const Vector<CodeEntry*>& path);
private:
- const char* GetFunctionName(String* name);
+ INLINE(const char* GetFunctionName(String* name));
+ INLINE(const char* GetFunctionName(const char* name));
const char* GetName(String* name);
const char* GetName(int args_count);
@@ -283,11 +286,18 @@
void RecordTickSample(const TickSample& sample);
INLINE(CodeMap* code_map()) { return &code_map_; }
+
+ static const char* kAnonymousFunctionName;
+ static const char* kProgramEntryName;
+ static const char* kGarbageCollectorEntryName;
private:
+ INLINE(CodeEntry* EntryForVMState(StateTag tag));
+
CpuProfilesCollection* profiles_;
CodeMap code_map_;
CodeEntry* program_entry_;
+ CodeEntry* gc_entry_;
DISALLOW_COPY_AND_ASSIGN(ProfileGenerator);
};
=======================================
--- /branches/bleeding_edge/test/cctest/test-cpu-profiler.cc Tue Apr 6
03:36:38 2010
+++ /branches/bleeding_edge/test/cctest/test-cpu-profiler.cc Wed Apr 7
07:18:26 2010
@@ -47,6 +47,7 @@
i::Address frame2 = NULL,
i::Address frame3 = NULL) {
i::TickSample* sample = proc->TickSampleEvent();
+ sample->state = i::OTHER;
sample->pc = frame1;
sample->function = frame1;
sample->frames_count = 0;
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
To unsubscribe, reply using "remove me" as the subject.