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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4357 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a4df380f
......@@ -217,14 +217,18 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
}
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 @@ void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
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 @@ void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
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()));
......
......@@ -65,6 +65,20 @@ TickSample* ProfilerEventsProcessor::TickSampleEvent() {
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
#endif // ENABLE_CPP_PROFILES_PROCESSOR
......
......@@ -57,6 +57,7 @@ void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
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 @@ void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
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 @@ void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
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 @@ void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
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 @@ void ProfilerEventsProcessor::RegExpCodeCreateEvent(
String* name,
Address start,
unsigned size) {
if (FilterOutCodeCreateEvent(tag)) return;
CodeEventsContainer evt_rec;
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->type = CodeEventRecord::CODE_CREATION;
......
......@@ -104,9 +104,10 @@ class CodeAliasEventRecord : public CodeEventRecord {
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 @@ class ProfilerEventsProcessor : public Thread {
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 @@ class CpuProfiler {
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:
......
......@@ -471,6 +471,11 @@ struct AccessorDescriptor {
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
......
......@@ -29,6 +29,7 @@
#define V8_LOG_INL_H_
#include "log.h"
#include "cpu-profiler.h"
namespace v8 {
namespace internal {
......@@ -55,10 +56,13 @@ inline const char* StateToString(StateTag state) {
}
}
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 @@ VMState::~VMState() {
}
#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
......
......@@ -1337,17 +1337,20 @@ void Logger::LogCompiledFunctions() {
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.
......
......@@ -148,6 +148,11 @@ class Logger {
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 @@ class Logger {
// 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).
......
......@@ -728,52 +728,47 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
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
......
......@@ -547,17 +547,17 @@ class Sampler::PlatformData : public Malloced {
// 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 @@ class Sampler::PlatformData : public Malloced {
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_);
}
......
......@@ -1806,37 +1806,32 @@ class Sampler::PlatformData : public Malloced {
// 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_);
}
......
......@@ -516,17 +516,17 @@ class Socket {
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.
......
......@@ -49,10 +49,13 @@ CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
}
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;
}
......@@ -86,6 +89,33 @@ bool CpuProfilesCollection::is_last_profile() {
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
#endif // ENABLE_CPP_PROFILES_PROCESSOR
......
......@@ -383,7 +383,7 @@ CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
const char* name) {
CodeEntry* entry = new CodeEntry(tag,
CodeEntry::kEmptyNamePrefix,
name,
GetFunctionName(name),
"",
v8::CpuProfileNode::kNoLineNumberInfo);
code_entries_.Add(entry);
......@@ -416,13 +416,6 @@ CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
}
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) {
if (name->IsString()) {
char* c_name =
......@@ -473,44 +466,56 @@ void CpuProfilesCollection::AddPathToCurrentProfiles(
}
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);
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;
} else {
CodeEntry* pc_entry = *entries.start();
if (pc_entry == NULL || pc_entry->is_js_function())
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())
*entry = NULL;
}
entry++;
}
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);
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);
}
......
......@@ -44,7 +44,7 @@ class CodeEntry {
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_; }
......@@ -52,6 +52,8 @@ class CodeEntry {
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;
private:
......@@ -223,7 +225,8 @@ class CpuProfilesCollection {
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);
......@@ -284,10 +287,17 @@ class ProfileGenerator {
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);
};
......
......@@ -47,6 +47,7 @@ static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
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;
......
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