C++ profiles processor: wire up to VM.

If 'shell' is compiled with 'cppprofilesprocessor=on' and run
with '--prof' flag, top-down and bottom-up call trees are printed
on shell exit.

Review URL: http://codereview.chromium.org/1582004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4343 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 388ad028
......@@ -800,7 +800,7 @@ Handle<Object> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
NULL,
Code::ComputeFlags(Code::REGEXP),
masm_->CodeObject());
LOG(RegExpCodeCreateEvent(*code, *source));
PROFILE(RegExpCodeCreateEvent(*code, *source));
return Handle<Object>::cast(code);
}
......
......@@ -1493,8 +1493,8 @@ void Builtins::Setup(bool create_heap_objects) {
}
}
// Log the event and add the code to the builtins array.
LOG(CodeCreateEvent(Logger::BUILTIN_TAG,
Code::cast(code), functions[i].s_name));
PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
Code::cast(code), functions[i].s_name));
builtins_[i] = code;
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_builtin_code) {
......
......@@ -64,7 +64,7 @@ void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) {
OPROFILE(CreateNativeCodeRegion(GetName(),
code->instruction_start(),
code->instruction_size()));
LOG(CodeCreateEvent(Logger::STUB_TAG, code, GetName()));
PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, GetName()));
Counters::total_stubs_code_size.Increment(code->instruction_size());
#ifdef ENABLE_DISASSEMBLER
......
......@@ -235,7 +235,7 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
bool CodeGenerator::ShouldGenerateLog(Expression* type) {
ASSERT(type != NULL);
if (!Logger::is_logging()) return false;
if (!Logger::is_logging() && !CpuProfiler::is_profiling()) return false;
Handle<String> name = Handle<String>::cast(type->AsLiteral()->handle());
if (FLAG_log_regexp) {
static Vector<const char> kRegexp = CStrVector("regexp");
......
......@@ -217,14 +217,14 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
}
if (script->name()->IsString()) {
LOG(CodeCreateEvent(is_eval ? Logger::EVAL_TAG : Logger::SCRIPT_TAG,
*code, String::cast(script->name())));
PROFILE(CodeCreateEvent(is_eval ? Logger::EVAL_TAG : Logger::SCRIPT_TAG,
*code, String::cast(script->name())));
OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
code->instruction_start(),
code->instruction_size()));
} else {
LOG(CodeCreateEvent(is_eval ? Logger::EVAL_TAG : Logger::SCRIPT_TAG,
*code, ""));
PROFILE(CodeCreateEvent(is_eval ? Logger::EVAL_TAG : Logger::SCRIPT_TAG,
*code, ""));
OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
code->instruction_start(),
code->instruction_size()));
......@@ -585,20 +585,22 @@ void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
// Log the code generation. If source information is available
// include script name and line number. Check explicitly whether
// logging is enabled as finding the line number is not free.
if (Logger::is_logging() || OProfileAgent::is_enabled()) {
if (Logger::is_logging()
|| OProfileAgent::is_enabled()
|| CpuProfiler::is_profiling()) {
Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
if (script->name()->IsString()) {
int line_num = GetScriptLineNumber(script, start_position) + 1;
USE(line_num);
LOG(CodeCreateEvent(tag, *code, *func_name,
String::cast(script->name()), line_num));
PROFILE(CodeCreateEvent(tag, *code, *func_name,
String::cast(script->name()), line_num));
OPROFILE(CreateNativeCodeRegion(*func_name,
String::cast(script->name()),
line_num,
code->instruction_start(),
code->instruction_size()));
} else {
LOG(CodeCreateEvent(tag, *code, *func_name));
PROFILE(CodeCreateEvent(tag, *code, *func_name));
OPROFILE(CreateNativeCodeRegion(*func_name,
code->instruction_start(),
code->instruction_size()));
......
......@@ -28,16 +28,36 @@
#ifndef V8_CPU_PROFILER_INL_H_
#define V8_CPU_PROFILER_INL_H_
#include "cpu-profiler.h"
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
#include "circular-queue-inl.h"
#include "profile-generator-inl.h"
#include "cpu-profiler.h"
namespace v8 {
namespace internal {
void CodeCreateEventRecord::UpdateCodeMap(CodeMap* code_map) {
code_map->AddCode(start, entry, size);
}
void CodeMoveEventRecord::UpdateCodeMap(CodeMap* code_map) {
code_map->MoveCode(from, to);
}
void CodeDeleteEventRecord::UpdateCodeMap(CodeMap* code_map) {
code_map->DeleteCode(start);
}
void CodeAliasEventRecord::UpdateCodeMap(CodeMap* code_map) {
code_map->AddAlias(alias, start);
}
TickSample* ProfilerEventsProcessor::TickSampleEvent() {
TickSampleEventRecord* evt =
TickSampleEventRecord::cast(ticks_buffer_.Enqueue());
......
......@@ -25,12 +25,14 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
#include "v8.h"
#include "cpu-profiler-inl.h"
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
#include "log-inl.h"
namespace v8 {
namespace internal {
......@@ -49,6 +51,21 @@ ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
enqueue_order_(0) { }
void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
const char* prefix,
String* name,
Address start) {
CodeEventsContainer evt_rec;
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->type = CodeEventRecord::CODE_CREATION;
rec->order = ++enqueue_order_;
rec->start = start;
rec->entry = generator_->NewCodeEntry(tag, prefix, name);
rec->size = 1;
events_buffer_.Enqueue(evt_rec);
}
void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
String* name,
String* resource_name,
......@@ -196,6 +213,254 @@ void ProfilerEventsProcessor::Run() {
while (ProcessTicks(dequeue_order) && ProcessCodeEvent(&dequeue_order)) { }
}
CpuProfiler* CpuProfiler::singleton_ = NULL;
void CpuProfiler::StartProfiling(const char* title) {
ASSERT(singleton_ != NULL);
singleton_->StartCollectingProfile(title);
}
void CpuProfiler::StartProfiling(String* title) {
ASSERT(singleton_ != NULL);
singleton_->StartCollectingProfile(title);
}
CpuProfile* CpuProfiler::StopProfiling(const char* title) {
ASSERT(singleton_ != NULL);
return singleton_->StopCollectingProfile(title);
}
CpuProfile* CpuProfiler::StopProfiling(String* title) {
ASSERT(singleton_ != NULL);
return singleton_->StopCollectingProfile(title);
}
int CpuProfiler::GetProfilesCount() {
ASSERT(singleton_ != NULL);
return singleton_->profiles_->profiles()->length();
}
CpuProfile* CpuProfiler::GetProfile(int index) {
ASSERT(singleton_ != NULL);
return singleton_->profiles_->profiles()->at(index);
}
CpuProfile* CpuProfiler::FindProfile(unsigned uid) {
ASSERT(singleton_ != NULL);
return singleton_->profiles_->GetProfile(uid);
}
TickSample* CpuProfiler::TickSampleEvent() {
ASSERT(singleton_ != NULL);
if (singleton_->is_profiling()) {
return singleton_->processor_->TickSampleEvent();
} else {
return NULL;
}
}
void CpuProfiler::CallbackEvent(String* name, Address entry_point) {
singleton_->processor_->CallbackCreateEvent(
Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, const char* comment) {
singleton_->processor_->CodeCreateEvent(
tag, comment, code->address(), code->ExecutableSize());
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, String* name) {
singleton_->processor_->CodeCreateEvent(
tag,
name,
Heap::empty_string(),
CodeEntry::kNoLineNumberInfo,
code->address(),
code->ExecutableSize());
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, String* name,
String* source, int line) {
singleton_->processor_->CodeCreateEvent(
tag,
name,
source,
line,
code->address(),
code->ExecutableSize());
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, int args_count) {
singleton_->processor_->CodeCreateEvent(
tag,
args_count,
code->address(),
code->ExecutableSize());
}
void CpuProfiler::CodeMoveEvent(Address from, Address to) {
singleton_->processor_->CodeMoveEvent(from, to);
}
void CpuProfiler::CodeDeleteEvent(Address from) {
singleton_->processor_->CodeDeleteEvent(from);
}
void CpuProfiler::FunctionCreateEvent(JSFunction* function) {
singleton_->processor_->FunctionCreateEvent(
function->address(), function->code()->address());
}
void CpuProfiler::FunctionMoveEvent(Address from, Address to) {
singleton_->processor_->FunctionMoveEvent(from, to);
}
void CpuProfiler::FunctionDeleteEvent(Address from) {
singleton_->processor_->FunctionDeleteEvent(from);
}
void CpuProfiler::GetterCallbackEvent(String* name, Address entry_point) {
singleton_->processor_->CallbackCreateEvent(
Logger::CALLBACK_TAG, "get ", name, entry_point);
}
void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
singleton_->processor_->CodeCreateEvent(
Logger::REG_EXP_TAG,
source,
Heap::empty_string(),
CodeEntry::kNoLineNumberInfo,
code->address(),
code->ExecutableSize());
}
void CpuProfiler::SetterCallbackEvent(String* name, Address entry_point) {
singleton_->processor_->CallbackCreateEvent(
Logger::CALLBACK_TAG, "set ", name, entry_point);
}
CpuProfiler::CpuProfiler()
: profiles_(new CpuProfilesCollection()),
next_profile_uid_(1),
generator_(NULL),
processor_(NULL) {
}
CpuProfiler::~CpuProfiler() {
delete profiles_;
}
void CpuProfiler::StartCollectingProfile(const char* title) {
if (profiles_->StartProfiling(title, ++next_profile_uid_)) {
StartProcessorIfNotStarted();
}
}
void CpuProfiler::StartCollectingProfile(String* title) {
if (profiles_->StartProfiling(title, ++next_profile_uid_)) {
StartProcessorIfNotStarted();
}
}
void CpuProfiler::StartProcessorIfNotStarted() {
if (processor_ == NULL) {
generator_ = new ProfileGenerator(profiles_);
processor_ = new ProfilerEventsProcessor(generator_);
processor_->Start();
// Enumerate stuff we already have in the heap.
if (Heap::HasBeenSetup()) {
Logger::LogCodeObjects();
Logger::LogCompiledFunctions();
Logger::LogFunctionObjects();
Logger::LogAccessorCallbacks();
}
// Enable stack sampling.
Logger::ticker_->Start();
}
}
CpuProfile* CpuProfiler::StopCollectingProfile(const char* title) {
StopProcessorIfLastProfile();
CpuProfile* result = profiles_->StopProfiling(title);
if (result != NULL) {
result->Print();
}
return result;
}
CpuProfile* CpuProfiler::StopCollectingProfile(String* title) {
StopProcessorIfLastProfile();
return profiles_->StopProfiling(title);
}
void CpuProfiler::StopProcessorIfLastProfile() {
if (profiles_->is_last_profile()) {
Logger::ticker_->Stop();
processor_->Stop();
processor_->Join();
delete processor_;
delete generator_;
processor_ = NULL;
generator_ = NULL;
}
}
} } // namespace v8::internal
#endif // ENABLE_CPP_PROFILES_PROCESSOR
namespace v8 {
namespace internal {
void CpuProfiler::Setup() {
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
if (singleton_ == NULL) {
singleton_ = new CpuProfiler();
}
#endif
}
void CpuProfiler::TearDown() {
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
if (singleton_ != NULL) {
delete singleton_;
}
singleton_ = NULL;
#endif
}
} } // namespace v8::internal
......@@ -31,11 +31,18 @@
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
#include "circular-queue.h"
#include "profile-generator.h"
namespace v8 {
namespace internal {
// Forward declarations.
class CodeEntry;
class CodeMap;
class CpuProfile;
class CpuProfilesCollection;
class ProfileGenerator;
#define CODE_EVENTS_TYPE_LIST(V) \
V(CODE_CREATION, CodeCreateEventRecord) \
V(CODE_MOVE, CodeMoveEventRecord) \
......@@ -64,9 +71,7 @@ class CodeCreateEventRecord : public CodeEventRecord {
CodeEntry* entry;
unsigned size;
INLINE(void UpdateCodeMap(CodeMap* code_map)) {
code_map->AddCode(start, entry, size);
}
INLINE(void UpdateCodeMap(CodeMap* code_map));
};
......@@ -75,9 +80,7 @@ class CodeMoveEventRecord : public CodeEventRecord {
Address from;
Address to;
INLINE(void UpdateCodeMap(CodeMap* code_map)) {
code_map->MoveCode(from, to);
}
INLINE(void UpdateCodeMap(CodeMap* code_map));
};
......@@ -85,9 +88,7 @@ class CodeDeleteEventRecord : public CodeEventRecord {
public:
Address start;
INLINE(void UpdateCodeMap(CodeMap* code_map)) {
code_map->DeleteCode(start);
}
INLINE(void UpdateCodeMap(CodeMap* code_map));
};
......@@ -96,9 +97,7 @@ class CodeAliasEventRecord : public CodeEventRecord {
Address alias;
Address start;
INLINE(void UpdateCodeMap(CodeMap* code_map)) {
code_map->AddAlias(alias, start);
}
INLINE(void UpdateCodeMap(CodeMap* code_map));
};
......@@ -133,6 +132,9 @@ class ProfilerEventsProcessor : public Thread {
INLINE(bool running()) { return running_; }
// Events adding methods. Called by VM threads.
void CallbackCreateEvent(Logger::LogEventsAndTags tag,
const char* prefix, String* name,
Address start);
void CodeCreateEvent(Logger::LogEventsAndTags tag,
String* name,
String* resource_name, int line_number,
......@@ -176,6 +178,91 @@ class ProfilerEventsProcessor : public Thread {
} } // namespace v8::internal
#define PROFILE(Call) \
LOG(Call); \
do { \
if (v8::internal::CpuProfiler::is_profiling()) { \
v8::internal::CpuProfiler::Call; \
} \
} while (false)
#else
#define PROFILE(Call) LOG(Call)
#endif // ENABLE_CPP_PROFILES_PROCESSOR
namespace v8 {
namespace internal {
class CpuProfiler {
public:
static void Setup();
static void TearDown();
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
static void StartProfiling(const char* title);
static void StartProfiling(String* title);
static CpuProfile* StopProfiling(const char* title);
static CpuProfile* StopProfiling(String* title);
static int GetProfilesCount();
static CpuProfile* GetProfile(int index);
static CpuProfile* FindProfile(unsigned uid);
// Invoked from stack sampler (thread or signal handler.)
static TickSample* TickSampleEvent();
// Must be called via PROFILE macro, otherwise will crash when
// profiling is not enabled.
static void CallbackEvent(String* name, Address entry_point);
static void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, const char* comment);
static void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, String* name);
static void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, String* name,
String* source, int line);
static void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, int args_count);
static void CodeMoveEvent(Address from, Address to);
static void CodeDeleteEvent(Address from);
static void FunctionCreateEvent(JSFunction* function);
static void FunctionMoveEvent(Address from, Address to);
static void FunctionDeleteEvent(Address from);
static void GetterCallbackEvent(String* name, Address entry_point);
static void RegExpCodeCreateEvent(Code* code, String* source);
static void SetterCallbackEvent(String* name, Address entry_point);
static INLINE(bool is_profiling()) {
ASSERT(singleton_ != NULL);
return singleton_->processor_ != NULL;
}
private:
CpuProfiler();
~CpuProfiler();
void StartCollectingProfile(const char* title);
void StartCollectingProfile(String* title);
void StartProcessorIfNotStarted();
CpuProfile* StopCollectingProfile(const char* title);
CpuProfile* StopCollectingProfile(String* title);
void StopProcessorIfLastProfile();
CpuProfilesCollection* profiles_;
unsigned next_profile_uid_;
ProfileGenerator* generator_;
ProfilerEventsProcessor* processor_;
static CpuProfiler* singleton_;
#else
static INLINE(bool is_profiling()) { return false; }
#endif // ENABLE_CPP_PROFILES_PROCESSOR
private:
DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
};
} } // namespace v8::internal
#endif // V8_CPU_PROFILER_H_
......@@ -737,7 +737,7 @@ bool CompileLazy(Handle<JSFunction> function,
ClearExceptionFlag flag) {
CompilationInfo info(function, 0, receiver);
bool result = CompileLazyHelper(&info, flag);
LOG(FunctionCreateEvent(*function));
PROFILE(FunctionCreateEvent(*function));
return result;
}
......@@ -747,7 +747,7 @@ bool CompileLazyInLoop(Handle<JSFunction> function,
ClearExceptionFlag flag) {
CompilationInfo info(function, 1, receiver);
bool result = CompileLazyHelper(&info, flag);
LOG(FunctionCreateEvent(*function));
PROFILE(FunctionCreateEvent(*function));
return result;
}
......
......@@ -123,8 +123,8 @@ void CpuFeatures::Probe() {
Code::ComputeFlags(Code::STUB),
Handle<Code>::null());
if (!code->IsCode()) return;
LOG(CodeCreateEvent(Logger::BUILTIN_TAG,
Code::cast(code), "CpuFeatures::Probe"));
PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
Code::cast(code), "CpuFeatures::Probe"));
typedef uint64_t (*F0)();
F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
supported_ = probe();
......
......@@ -832,7 +832,7 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
NULL,
Code::ComputeFlags(Code::REGEXP),
masm_->CodeObject());
LOG(RegExpCodeCreateEvent(*code, *source));
PROFILE(RegExpCodeCreateEvent(*code, *source));
return Handle<Object>::cast(code);
}
......
......@@ -143,15 +143,14 @@ bool Profiler::paused_ = false;
// StackTracer implementation
//
void StackTracer::Trace(TickSample* sample) {
if (sample->state == GC) {
sample->frames_count = 0;
return;
}
sample->function = NULL;
sample->frames_count = 0;
if (sample->state == GC) return;
const Address js_entry_sp = Top::js_entry_sp(Top::GetCurrentThread());
if (js_entry_sp == 0) {
// Not executing JS now.
sample->frames_count = 0;
return;
}
......@@ -183,6 +182,8 @@ void StackTracer::Trace(TickSample* sample) {
// Ticker used to provide ticks to the profiler and the sliding state
// window.
//
#ifndef ENABLE_CPP_PROFILES_PROCESSOR
class Ticker: public Sampler {
public:
explicit Ticker(int interval):
......@@ -224,6 +225,8 @@ class Ticker: public Sampler {
Profiler* profiler_;
};
#endif // ENABLE_CPP_PROFILES_PROCESSOR
//
// SlidingStateWindow implementation.
......@@ -1300,7 +1303,7 @@ void Logger::LogCodeObject(Object* object) {
tag = Logger::CALL_IC_TAG;
break;
}
LOG(CodeCreateEvent(tag, code_object, description));
PROFILE(CodeCreateEvent(tag, code_object, description));
}
}
......@@ -1334,16 +1337,16 @@ void Logger::LogCompiledFunctions() {
Handle<String> script_name(String::cast(script->name()));
int line_num = GetScriptLineNumber(script, shared->start_position());
if (line_num > 0) {
LOG(CodeCreateEvent(Logger::LAZY_COMPILE_TAG,
shared->code(), *func_name,
*script_name, line_num + 1));
PROFILE(CodeCreateEvent(Logger::LAZY_COMPILE_TAG,
shared->code(), *func_name,
*script_name, line_num + 1));
} else {
// Can't distinguish enum and script here, so always use Script.
LOG(CodeCreateEvent(Logger::SCRIPT_TAG,
shared->code(), *script_name));
PROFILE(CodeCreateEvent(Logger::SCRIPT_TAG,
shared->code(), *script_name));
}
} else {
LOG(CodeCreateEvent(
PROFILE(CodeCreateEvent(
Logger::LAZY_COMPILE_TAG, shared->code(), *func_name));
}
} else if (shared->IsApiFunction()) {
......@@ -1354,10 +1357,10 @@ void Logger::LogCompiledFunctions() {
CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
Object* callback_obj = call_data->callback();
Address entry_point = v8::ToCData<Address>(callback_obj);
LOG(CallbackEvent(*func_name, entry_point));
PROFILE(CallbackEvent(*func_name, entry_point));
}
} else {
LOG(CodeCreateEvent(
PROFILE(CodeCreateEvent(
Logger::LAZY_COMPILE_TAG, shared->code(), *func_name));
}
}
......@@ -1373,7 +1376,7 @@ void Logger::LogFunctionObjects() {
if (!obj->IsJSFunction()) continue;
JSFunction* jsf = JSFunction::cast(obj);
if (!jsf->is_compiled()) continue;
LOG(FunctionCreateEvent(jsf));
PROFILE(FunctionCreateEvent(jsf));
}
}
......@@ -1388,11 +1391,11 @@ void Logger::LogAccessorCallbacks() {
String* name = String::cast(ai->name());
Address getter_entry = v8::ToCData<Address>(ai->getter());
if (getter_entry != 0) {
LOG(GetterCallbackEvent(name, getter_entry));
PROFILE(GetterCallbackEvent(name, getter_entry));
}
Address setter_entry = v8::ToCData<Address>(ai->setter());
if (setter_entry != 0) {
LOG(SetterCallbackEvent(name, setter_entry));
PROFILE(SetterCallbackEvent(name, setter_entry));
}
}
}
......@@ -1505,6 +1508,11 @@ bool Logger::Setup() {
}
}
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
// Disable old logging, as we are using the same '--prof' flag.
logging_nesting_ = 0;
#endif
LogMessageBuilder::set_write_failure_handler(StopLoggingAndProfiling);
return true;
......@@ -1558,5 +1566,4 @@ void Logger::EnableSlidingStateWindow() {
#endif
}
} } // namespace v8::internal
......@@ -87,7 +87,6 @@ class CompressionHelper;
#define LOG(Call) ((void) 0)
#endif
class VMState BASE_EMBEDDED {
#ifdef ENABLE_LOGGING_AND_PROFILING
public:
......@@ -378,6 +377,8 @@ class Logger {
static int logging_nesting_;
static int cpu_profiler_nesting_;
static int heap_profiler_nesting_;
friend class CpuProfiler;
#else
static bool is_logging() { return false; }
#endif
......@@ -391,6 +392,26 @@ class StackTracer : public AllStatic {
};
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
class Ticker: public Sampler {
public:
explicit Ticker(int interval):
Sampler(interval, FLAG_prof) {}
void SampleStack(TickSample* sample) {
StackTracer::Trace(sample);
}
void Tick(TickSample* sample) { }
void SetWindow(SlidingStateWindow* window) { }
void ClearWindow() { }
void SetProfiler(Profiler* profiler) { }
void ClearProfiler() { }
};
#endif // ENABLE_CPP_PROFILES_PROCESSOR
} } // namespace v8::internal
#endif // V8_LOG_H_
......@@ -2099,7 +2099,7 @@ int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj,
HeapObject* copied_to = HeapObject::FromAddress(new_addr);
if (copied_to->IsJSFunction()) {
LOG(FunctionMoveEvent(old_addr, new_addr));
PROFILE(FunctionMoveEvent(old_addr, new_addr));
}
return obj_size;
......@@ -2147,7 +2147,7 @@ int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) {
// May also update inline cache target.
Code::cast(copied_to)->Relocate(new_addr - old_addr);
// Notify the logger that compiled code has moved.
LOG(CodeMoveEvent(old_addr, new_addr));
PROFILE(CodeMoveEvent(old_addr, new_addr));
}
return obj_size;
......@@ -2187,7 +2187,7 @@ int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
HeapObject* copied_to = HeapObject::FromAddress(new_addr);
if (copied_to->IsJSFunction()) {
LOG(FunctionMoveEvent(old_addr, new_addr));
PROFILE(FunctionMoveEvent(old_addr, new_addr));
}
return obj_size;
......@@ -2209,9 +2209,9 @@ void MarkCompactCollector::RebuildRSets() {
void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (obj->IsCode()) {
LOG(CodeDeleteEvent(obj->address()));
PROFILE(CodeDeleteEvent(obj->address()));
} else if (obj->IsJSFunction()) {
LOG(FunctionDeleteEvent(obj->address()));
PROFILE(FunctionDeleteEvent(obj->address()));
}
#endif
}
......
......@@ -727,44 +727,62 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
if (signal != SIGPROF) return;
if (active_sampler_ == NULL) return;
TickSample sample;
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
if (Logger::state() == GC || !IsVmThread()) return;
TickSample* sample = NULL;
#else
TickSample sample_obj;
TickSample* sample = &sample_obj;
// We always sample the VM state.
sample.state = Logger::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
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
active_sampler_->SampleStack(sample);
#else
if (IsVmThread()) {
active_sampler_->SampleStack(sample);
}
#endif
if (IsVmThread())
active_sampler_->SampleStack(&sample);
}
}
active_sampler_->Tick(&sample);
#ifndef ENABLE_CPP_PROFILES_PROCESSOR
active_sampler_->Tick(sample);
#endif
#endif
}
......
......@@ -544,12 +544,19 @@ class Sampler::PlatformData : public Malloced {
// Sampler thread handler.
void Runner() {
// Loop until the sampler is disengaged.
while (sampler_->IsActive()) {
TickSample sample;
// 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;
#else
TickSample sample_obj;
TickSample* sample = &sample_obj;
// We always sample the VM state.
sample.state = Logger::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()
......@@ -580,19 +587,23 @@ class Sampler::PlatformData : public Malloced {
flavor,
reinterpret_cast<natural_t*>(&state),
&count) == KERN_SUCCESS) {
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);
#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);
}
}
thread_resume(profiled_thread_);
}
#ifndef ENABLE_CPP_PROFILES_PROCESSOR
// Invoke tick handler with program counter and stack pointer.
sampler_->Tick(&sample);
// Wait until next sampling.
usleep(sampler_->interval_ * 1000);
sampler_->Tick(sample);
#endif
}
}
};
......
......@@ -1803,37 +1803,48 @@ class Sampler::PlatformData : public Malloced {
// Context used for sampling the register state of the profiled thread.
CONTEXT context;
memset(&context, 0, sizeof(context));
// Loop until the sampler is disengaged.
while (sampler_->IsActive()) {
TickSample sample;
// 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;
#else
TickSample sample_obj;
TickSample* sample = &sample_obj;
// We always sample the VM state.
sample.state = Logger::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_);
}
#ifndef ENABLE_CPP_PROFILES_PROCESSOR
// Invoke tick handler with program counter and stack pointer.
sampler_->Tick(&sample);
// Wait until next sampling.
Sleep(sampler_->interval_);
sampler_->Tick(sample);
#endif
}
}
};
......
......@@ -527,7 +527,7 @@ class TickSample {
Address fp; // Frame pointer.
Address function; // The last called JS function.
StateTag state; // The state of the VM.
static const int kMaxFramesCount = 100;
static const int kMaxFramesCount = 64;
Address stack[kMaxFramesCount]; // Call stack.
int frames_count; // Number of captured frames.
};
......
......@@ -36,17 +36,19 @@ namespace v8 {
namespace internal {
CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
const char* name_prefix,
const char* name,
const char* resource_name,
int line_number)
: tag_(tag),
name_prefix_(name_prefix),
name_(name),
resource_name_(resource_name),
line_number_(line_number) {
}
bool CodeEntry::is_js_function() {
bool CodeEntry::is_js_function() const {
return tag_ == Logger::FUNCTION_TAG
|| tag_ == Logger::LAZY_COMPILE_TAG
|| tag_ == Logger::SCRIPT_TAG;
......
......@@ -34,6 +34,11 @@
namespace v8 {
namespace internal {
const char* CodeEntry::kEmptyNamePrefix = "";
const int CodeEntry::kNoLineNumberInfo = -1;
ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
HashMap::Entry* map_entry =
children_.Lookup(entry, CodeEntryHash(entry), false);
......@@ -56,9 +61,10 @@ ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) {
void ProfileNode::Print(int indent) {
OS::Print("%5u %5u %*c %s\n",
OS::Print("%5u %5u %*c %s%s\n",
total_ticks_, self_ticks_,
indent, ' ',
entry_ != NULL ? entry_->name_prefix() : "",
entry_ != NULL ? entry_->name() : "");
for (HashMap::Entry* p = children_.Start();
p != NULL;
......@@ -353,6 +359,7 @@ CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
String* resource_name,
int line_number) {
CodeEntry* entry = new CodeEntry(tag,
CodeEntry::kEmptyNamePrefix,
GetName(name),
GetName(resource_name),
line_number);
......@@ -364,9 +371,23 @@ CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
const char* name) {
CodeEntry* entry = new CodeEntry(tag,
CodeEntry::kEmptyNamePrefix,
name,
"",
kNoLineNumberInfo);
CodeEntry::kNoLineNumberInfo);
code_entries_.Add(entry);
return entry;
}
CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
const char* name_prefix,
String* name) {
CodeEntry* entry = new CodeEntry(tag,
name_prefix,
GetName(name),
"",
CodeEntry::kNoLineNumberInfo);
code_entries_.Add(entry);
return entry;
}
......@@ -375,9 +396,10 @@ CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
int args_count) {
CodeEntry* entry = new CodeEntry(tag,
"args_count: ",
GetName(args_count),
"",
kNoLineNumberInfo);
CodeEntry::kNoLineNumberInfo);
code_entries_.Add(entry);
return entry;
}
......@@ -413,8 +435,7 @@ const char* CpuProfilesCollection::GetName(int args_count) {
if (args_count_names_[args_count] == NULL) {
const int kMaximumNameLength = 32;
char* name = NewArray<char>(kMaximumNameLength);
OS::SNPrintF(Vector<char>(name, kMaximumNameLength),
"args_count: %d", args_count);
OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", args_count);
args_count_names_[args_count] = name;
}
return args_count_names_[args_count];
......
......@@ -38,18 +38,25 @@ namespace internal {
class CodeEntry {
public:
// CodeEntry doesn't own name strings, just references them.
INLINE(CodeEntry(Logger::LogEventsAndTags tag_,
const char* name_,
const char* resource_name_,
int line_number_));
INLINE(bool is_js_function());
INLINE(const char* name()) { return name_; }
INLINE(const char* resource_name()) { return name_; }
INLINE(int line_number()) { return line_number_; }
INLINE(CodeEntry(Logger::LogEventsAndTags tag,
const char* name_prefix,
const char* name,
const char* resource_name,
int line_number));
INLINE(bool is_js_function() const);
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_; }
static const char* kEmptyNamePrefix;
static const int kNoLineNumberInfo;
private:
Logger::LogEventsAndTags tag_;
const char* name_prefix_;
const char* name_;
const char* resource_name_;
int line_number_;
......@@ -204,14 +211,13 @@ class CpuProfilesCollection {
CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
String* name, String* resource_name, int line_number);
CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, const char* name);
CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
const char* name_prefix, String* name);
CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, int args_count);
// Called from profile generator thread.
void AddPathToCurrentProfiles(const Vector<CodeEntry*>& path);
// This will be moved to V8 API.
static const int kNoLineNumberInfo = -1;
private:
const char* GetName(String* name);
const char* GetName(int args_count);
......@@ -258,6 +264,12 @@ class ProfileGenerator {
return profiles_->NewCodeEntry(tag, name);
}
INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
const char* name_prefix,
String* name)) {
return profiles_->NewCodeEntry(tag, name_prefix, name);
}
INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
int args_count)) {
return profiles_->NewCodeEntry(tag, args_count);
......
This diff is collapsed.
......@@ -60,6 +60,14 @@ bool V8::Initialize(Deserializer* des) {
// Enable logging before setting up the heap
Logger::Setup();
CpuProfiler::Setup();
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
if (FLAG_prof && FLAG_prof_auto) {
CpuProfiler::StartProfiling("internal.auto");
}
#endif
// Setup the platform OS support.
OS::Setup();
......@@ -135,6 +143,12 @@ void V8::SetFatalError() {
void V8::TearDown() {
if (!has_been_setup_ || has_been_disposed_) return;
#ifdef ENABLE_CPP_PROFILES_PROCESSOR
if (FLAG_prof && FLAG_prof_auto) {
CpuProfiler::StopProfiling("internal.auto");
}
#endif
OProfileAgent::TearDown();
if (FLAG_preemption) {
......@@ -148,6 +162,9 @@ void V8::TearDown() {
Top::TearDown();
Heap::TearDown();
CpuProfiler::TearDown();
Logger::TearDown();
is_running_ = false;
......
......@@ -67,6 +67,7 @@
#include "spaces-inl.h"
#include "heap-inl.h"
#include "log-inl.h"
#include "cpu-profiler-inl.h"
#include "handles-inl.h"
namespace v8 {
......
......@@ -119,8 +119,8 @@ void CpuFeatures::Probe() {
Object* code =
Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB), NULL);
if (!code->IsCode()) return;
LOG(CodeCreateEvent(Logger::BUILTIN_TAG,
Code::cast(code), "CpuFeatures::Probe"));
PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
Code::cast(code), "CpuFeatures::Probe"));
typedef uint64_t (*F0)();
F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
supported_ = probe();
......
......@@ -905,7 +905,7 @@ Handle<Object> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
NULL,
Code::ComputeFlags(Code::REGEXP),
masm_->CodeObject());
LOG(RegExpCodeCreateEvent(*code, *source));
PROFILE(RegExpCodeCreateEvent(*code, *source));
return Handle<Object>::cast(code);
}
......
......@@ -110,7 +110,7 @@ TEST(CodeEvents) {
CHECK_EQ("bbb", entry2->name());
CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300));
CHECK_NE(NULL, entry3);
CHECK_EQ("args_count: 5", entry3->name());
CHECK_EQ("5", entry3->name());
CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400)));
CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500));
CHECK_NE(NULL, entry4);
......@@ -166,7 +166,7 @@ TEST(TickEvents) {
const i::List<ProfileNode*>* top_down_bbb_children =
top_down_root_children->last()->children();
CHECK_EQ(1, top_down_bbb_children->length());
CHECK_EQ("args_count: 5", top_down_bbb_children->last()->entry()->name());
CHECK_EQ("5", top_down_bbb_children->last()->entry()->name());
const i::List<ProfileNode*>* top_down_stub_children =
top_down_bbb_children->last()->children();
CHECK_EQ(1, top_down_stub_children->length());
......@@ -181,7 +181,7 @@ TEST(TickEvents) {
i::List<ProfileNode*> bottom_up_root_children(3);
bottom_up_root_children.AddAll(*bottom_up_root_children_unsorted);
bottom_up_root_children.Sort(&CompareProfileNodes);
CHECK_EQ("args_count: 5", bottom_up_root_children[0]->entry()->name());
CHECK_EQ("5", bottom_up_root_children[0]->entry()->name());
CHECK_EQ("bbb", bottom_up_root_children[1]->entry()->name());
CHECK_EQ("ddd", bottom_up_root_children[2]->entry()->name());
const i::List<ProfileNode*>* bottom_up_stub_children =
......@@ -194,7 +194,7 @@ TEST(TickEvents) {
const i::List<ProfileNode*>* bottom_up_ddd_children =
bottom_up_root_children[2]->children();
CHECK_EQ(1, bottom_up_ddd_children->length());
CHECK_EQ("args_count: 5", bottom_up_ddd_children->last()->entry()->name());
CHECK_EQ("5", bottom_up_ddd_children->last()->entry()->name());
const i::List<ProfileNode*>* bottom_up_ddd_stub_children =
bottom_up_ddd_children->last()->children();
CHECK_EQ(1, bottom_up_ddd_stub_children->length());
......
......@@ -13,6 +13,7 @@
#include "v8.h"
#include "log.h"
#include "cpu-profiler.h"
#include "v8threads.h"
#include "cctest.h"
......
......@@ -23,17 +23,17 @@ using i::Vector;
TEST(ProfileNodeFindOrAddChild) {
ProfileNode node(NULL);
CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa", "", 0);
CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
ProfileNode* childNode1 = node.FindOrAddChild(&entry1);
CHECK_NE(NULL, childNode1);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb", "", 0);
CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
ProfileNode* childNode2 = node.FindOrAddChild(&entry2);
CHECK_NE(NULL, childNode2);
CHECK_NE(childNode1, childNode2);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
CHECK_EQ(childNode2, node.FindOrAddChild(&entry2));
CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc", "", 0);
CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0);
ProfileNode* childNode3 = node.FindOrAddChild(&entry3);
CHECK_NE(NULL, childNode3);
CHECK_NE(childNode1, childNode3);
......@@ -74,9 +74,9 @@ class ProfileTreeTestHelper {
} // namespace
TEST(ProfileTreeAddPathFromStart) {
CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa", "", 0);
CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb", "", 0);
CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc", "", 0);
CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0);
ProfileTree tree;
ProfileTreeTestHelper helper(&tree);
CHECK_EQ(NULL, helper.Walk(&entry1));
......@@ -141,9 +141,9 @@ TEST(ProfileTreeAddPathFromStart) {
TEST(ProfileTreeAddPathFromEnd) {
CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa", "", 0);
CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb", "", 0);
CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc", "", 0);
CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0);
ProfileTree tree;
ProfileTreeTestHelper helper(&tree);
CHECK_EQ(NULL, helper.Walk(&entry1));
......@@ -221,8 +221,8 @@ TEST(ProfileTreeCalculateTotalTicks) {
CHECK_EQ(1, empty_tree.root()->total_ticks());
CHECK_EQ(1, empty_tree.root()->self_ticks());
CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa", "", 0);
CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb", "", 0);
CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
CodeEntry* e1_path[] = {&entry1};
Vector<CodeEntry*> e1_path_vec(
e1_path, sizeof(e1_path) / sizeof(e1_path[0]));
......@@ -260,7 +260,7 @@ TEST(ProfileTreeCalculateTotalTicks) {
CodeEntry* e2_path[] = {&entry2};
Vector<CodeEntry*> e2_path_vec(
e2_path, sizeof(e2_path) / sizeof(e2_path[0]));
CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc", "", 0);
CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0);
CodeEntry* e3_path[] = {&entry3};
Vector<CodeEntry*> e3_path_vec(
e3_path, sizeof(e3_path) / sizeof(e3_path[0]));
......@@ -321,10 +321,10 @@ static inline i::Address ToAddress(int n) {
TEST(CodeMapAddCode) {
CodeMap code_map;
CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa", "", 0);
CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb", "", 0);
CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc", "", 0);
CodeEntry entry4(i::Logger::FUNCTION_TAG, "ddd", "", 0);
CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", "", 0);
CodeEntry entry4(i::Logger::FUNCTION_TAG, "", "ddd", "", 0);
code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
code_map.AddCode(ToAddress(0x1900), &entry3, 0x50);
......@@ -351,8 +351,8 @@ TEST(CodeMapAddCode) {
TEST(CodeMapMoveAndDeleteCode) {
CodeMap code_map;
CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa", "", 0);
CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb", "", 0);
CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0);
CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", "", 0);
code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500)));
......
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