}
-bool ProfilerEventsProcessor::FilterOutCodeCreateEvent(
- Logger::LogEventsAndTags tag) {
- return FLAG_prof_browser_mode
- && (tag != Logger::CALLBACK_TAG
- && tag != Logger::FUNCTION_TAG
- && tag != Logger::LAZY_COMPILE_TAG
- && tag != Logger::REG_EXP_TAG
- && tag != Logger::SCRIPT_TAG);
-}
-
} } // namespace v8::internal
#endif // V8_CPU_PROFILER_INL_H_
}
-void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
- const char* prefix,
- Name* name,
- Address start) {
- if (FilterOutCodeCreateEvent(tag)) return;
- CodeEventsContainer evt_rec;
- CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->type = CodeEventRecord::CODE_CREATION;
- rec->order = ++enqueue_order_;
- rec->start = start;
- rec->entry = profiles_->NewCodeEntry(tag, prefix, name);
- rec->size = 1;
- rec->shared = NULL;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Name* name,
- String* resource_name,
- int line_number,
- Address start,
- unsigned size,
- Address shared,
- CompilationInfo* info) {
- if (FilterOutCodeCreateEvent(tag)) return;
- CodeEventsContainer evt_rec;
- CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->type = CodeEventRecord::CODE_CREATION;
- rec->order = ++enqueue_order_;
- rec->start = start;
- rec->entry = profiles_->NewCodeEntry(tag, name, resource_name, line_number);
- if (info) {
- rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
- }
- rec->size = size;
- rec->shared = shared;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-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;
- rec->order = ++enqueue_order_;
- rec->start = start;
- rec->entry = profiles_->NewCodeEntry(tag, name);
- rec->size = size;
- rec->shared = NULL;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-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;
- rec->order = ++enqueue_order_;
- rec->start = start;
- rec->entry = profiles_->NewCodeEntry(tag, args_count);
- rec->size = size;
- rec->shared = NULL;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-void ProfilerEventsProcessor::CodeMoveEvent(Address from, Address to) {
- CodeEventsContainer evt_rec;
- CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
- rec->type = CodeEventRecord::CODE_MOVE;
- rec->order = ++enqueue_order_;
- rec->from = from;
- rec->to = to;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-void ProfilerEventsProcessor::SharedFunctionInfoMoveEvent(Address from,
- Address to) {
- CodeEventsContainer evt_rec;
- SharedFunctionInfoMoveEventRecord* rec =
- &evt_rec.SharedFunctionInfoMoveEventRecord_;
- rec->type = CodeEventRecord::SHARED_FUNC_MOVE;
- rec->order = ++enqueue_order_;
- rec->from = from;
- rec->to = to;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-void ProfilerEventsProcessor::RegExpCodeCreateEvent(
- Logger::LogEventsAndTags tag,
- const char* prefix,
- String* name,
- Address start,
- unsigned size) {
- if (FilterOutCodeCreateEvent(tag)) return;
- CodeEventsContainer evt_rec;
- CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->type = CodeEventRecord::CODE_CREATION;
- rec->order = ++enqueue_order_;
- rec->start = start;
- rec->entry = profiles_->NewCodeEntry(tag, prefix, name);
- rec->size = size;
- events_buffer_.Enqueue(evt_rec);
+void ProfilerEventsProcessor::Enqueue(const CodeEventsContainer& event) {
+ event.generic.order = ++enqueue_order_;
+ events_buffer_.Enqueue(event);
}
}
+static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag) {
+ return FLAG_prof_browser_mode
+ && (tag != Logger::CALLBACK_TAG
+ && tag != Logger::FUNCTION_TAG
+ && tag != Logger::LAZY_COMPILE_TAG
+ && tag != Logger::REG_EXP_TAG
+ && tag != Logger::SCRIPT_TAG);
+}
+
+
void CpuProfiler::CallbackEvent(Name* name, Address entry_point) {
- processor_->CallbackCreateEvent(
- Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
+ if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = entry_point;
+ rec->entry = profiles_->NewCodeEntry(
+ Logger::CALLBACK_TAG,
+ profiles_->GetName(name),
+ TokenEnumerator::kInheritsSecurityToken);
+ rec->size = 1;
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, const char* comment) {
- processor_->CodeCreateEvent(
- tag, comment, code->address(), code->ExecutableSize());
+ Code* code,
+ const char* name) {
+ if (FilterOutCodeCreateEvent(tag)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
+ rec->size = code->ExecutableSize();
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, Name* name) {
- processor_->CodeCreateEvent(
- tag,
- name,
- isolate_->heap()->empty_string(),
- v8::CpuProfileNode::kNoLineNumberInfo,
- code->address(),
- code->ExecutableSize(),
- NULL,
- NULL);
+ Code* code,
+ Name* name) {
+ if (FilterOutCodeCreateEvent(tag)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
+ rec->size = code->ExecutableSize();
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
SharedFunctionInfo* shared,
CompilationInfo* info,
Name* name) {
- processor_->CodeCreateEvent(
- tag,
- name,
- isolate_->heap()->empty_string(),
- v8::CpuProfileNode::kNoLineNumberInfo,
- code->address(),
- code->ExecutableSize(),
- shared->address(),
- info);
+ if (FilterOutCodeCreateEvent(tag)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
+ rec->entry->set_no_frame_ranges(info ?
+ info->ReleaseNoFrameRanges() :
+ NULL);
+ rec->size = code->ExecutableSize();
+ rec->shared = shared->address();
+ processor_->Enqueue(evt_rec);
}
SharedFunctionInfo* shared,
CompilationInfo* info,
String* source, int line) {
- processor_->CodeCreateEvent(
+ if (FilterOutCodeCreateEvent(tag)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(
tag,
- shared->DebugName(),
- source,
- line,
- code->address(),
- code->ExecutableSize(),
- shared->address(),
- info);
+ profiles_->GetFunctionName(shared->DebugName()),
+ TokenEnumerator::kNoSecurityToken,
+ CodeEntry::kEmptyNamePrefix,
+ profiles_->GetName(source),
+ line);
+ rec->entry->set_no_frame_ranges(info ?
+ info->ReleaseNoFrameRanges() :
+ NULL);
+ rec->size = code->ExecutableSize();
+ rec->shared = shared->address();
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, int args_count) {
- processor_->CodeCreateEvent(
+ Code* code,
+ int args_count) {
+ if (FilterOutCodeCreateEvent(tag)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(
tag,
- args_count,
- code->address(),
- code->ExecutableSize());
+ profiles_->GetName(args_count),
+ TokenEnumerator::kInheritsSecurityToken,
+ "args_count: ");
+ rec->size = code->ExecutableSize();
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::CodeMoveEvent(Address from, Address to) {
- processor_->CodeMoveEvent(from, to);
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE);
+ CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
+ rec->from = from;
+ rec->to = to;
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
- processor_->SharedFunctionInfoMoveEvent(from, to);
+ CodeEventsContainer evt_rec(CodeEventRecord::SHARED_FUNC_MOVE);
+ SharedFunctionInfoMoveEventRecord* rec =
+ &evt_rec.SharedFunctionInfoMoveEventRecord_;
+ rec->from = from;
+ rec->to = to;
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::GetterCallbackEvent(Name* name, Address entry_point) {
- processor_->CallbackCreateEvent(
- Logger::CALLBACK_TAG, "get ", name, entry_point);
+ if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = entry_point;
+ rec->entry = profiles_->NewCodeEntry(
+ Logger::CALLBACK_TAG,
+ profiles_->GetName(name),
+ TokenEnumerator::kInheritsSecurityToken,
+ "get ");
+ rec->size = 1;
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
- processor_->RegExpCodeCreateEvent(
+ if (FilterOutCodeCreateEvent(Logger::REG_EXP_TAG)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(
Logger::REG_EXP_TAG,
- "RegExp: ",
- source,
- code->address(),
- code->ExecutableSize());
+ profiles_->GetName(source),
+ TokenEnumerator::kInheritsSecurityToken,
+ "RegExp: ");
+ rec->size = code->ExecutableSize();
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::SetterCallbackEvent(Name* name, Address entry_point) {
- processor_->CallbackCreateEvent(
- Logger::CALLBACK_TAG, "set ", name, entry_point);
+ if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = entry_point;
+ rec->entry = profiles_->NewCodeEntry(
+ Logger::CALLBACK_TAG,
+ profiles_->GetName(name),
+ TokenEnumerator::kInheritsSecurityToken,
+ "set ");
+ rec->size = 1;
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
}
+CpuProfiler::CpuProfiler(Isolate* isolate,
+ CpuProfilesCollection* test_profiles,
+ ProfileGenerator* test_generator,
+ ProfilerEventsProcessor* test_processor)
+ : isolate_(isolate),
+ profiles_(test_profiles),
+ next_profile_uid_(1),
+ token_enumerator_(new TokenEnumerator()),
+ generator_(test_generator),
+ processor_(test_processor),
+ need_to_stop_sampler_(false),
+ is_profiling_(false) {
+}
+
+
CpuProfiler::~CpuProfiler() {
delete token_enumerator_;
delete profiles_;
#undef DECLARE_TYPE
Type type;
- unsigned order;
+ mutable unsigned order;
};
};
+class CodeEventsContainer {
+ public:
+ explicit CodeEventsContainer(
+ CodeEventRecord::Type type = CodeEventRecord::NONE) {
+ generic.type = type;
+ }
+ union {
+ CodeEventRecord generic;
+#define DECLARE_CLASS(ignore, type) type type##_;
+ CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
+#undef DECLARE_TYPE
+ };
+};
+
+
// This class implements both the profile events processor thread and
// methods called by event producers: VM and stack sampler threads.
class ProfilerEventsProcessor : public Thread {
virtual void Run();
inline void Stop() { running_ = false; }
INLINE(bool running()) { return running_; }
+ void Enqueue(const CodeEventsContainer& event);
- // Events adding methods. Called by VM threads.
- void CallbackCreateEvent(Logger::LogEventsAndTags tag,
- const char* prefix, Name* name,
- Address start);
- void CodeCreateEvent(Logger::LogEventsAndTags tag,
- Name* name,
- String* resource_name, int line_number,
- Address start, unsigned size,
- Address shared,
- CompilationInfo* info);
- void CodeCreateEvent(Logger::LogEventsAndTags tag,
- const char* name,
- Address start, unsigned size);
- void CodeCreateEvent(Logger::LogEventsAndTags tag,
- int args_count,
- Address start, unsigned size);
- void CodeMoveEvent(Address from, Address to);
- void CodeDeleteEvent(Address from);
- void SharedFunctionInfoMoveEvent(Address from, Address to);
- void RegExpCodeCreateEvent(Logger::LogEventsAndTags tag,
- const char* prefix, String* name,
- Address start, unsigned size);
// Puts current stack into tick sample events buffer.
void AddCurrentStack();
INLINE(TickSample* TickSampleEvent());
private:
- union CodeEventsContainer {
- CodeEventRecord generic;
-#define DECLARE_CLASS(ignore, type) type type##_;
- CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
-#undef DECLARE_TYPE
- };
-
// Called from events processing thread (Run() method.)
bool ProcessCodeEvent(unsigned* dequeue_order);
bool ProcessTicks(unsigned dequeue_order);
- INLINE(static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag));
-
ProfileGenerator* generator_;
CpuProfilesCollection* profiles_;
bool running_;
class CpuProfiler {
public:
explicit CpuProfiler(Isolate* isolate);
+
+ CpuProfiler(Isolate* isolate,
+ CpuProfilesCollection* test_collection,
+ ProfileGenerator* test_generator,
+ ProfilerEventsProcessor* test_processor);
+
~CpuProfiler();
void StartProfiling(const char* title, bool record_samples = false);
CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
- const char* name_prefix,
const char* name,
int security_token_id,
+ const char* name_prefix,
const char* resource_name,
int line_number)
: tag_(tag),
ProfileTree::ProfileTree()
- : root_entry_(Logger::FUNCTION_TAG, "", "(root)"),
+ : root_entry_(Logger::FUNCTION_TAG, "(root)"),
next_node_id_(1),
root_(new ProfileNode(this, &root_entry_)) {
}
}
-CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
- Name* name,
- String* resource_name,
- int line_number) {
- CodeEntry* entry = new CodeEntry(tag,
- CodeEntry::kEmptyNamePrefix,
- GetFunctionName(name),
- TokenEnumerator::kNoSecurityToken,
- GetName(resource_name),
- line_number);
- code_entries_.Add(entry);
- return entry;
-}
-
-
-CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
- const char* name) {
- CodeEntry* entry = new CodeEntry(tag,
- CodeEntry::kEmptyNamePrefix,
- GetFunctionName(name));
- code_entries_.Add(entry);
- return entry;
-}
-
-
-CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
- const char* name_prefix,
- Name* name) {
- CodeEntry* entry = new CodeEntry(tag,
- name_prefix,
- GetName(name),
- TokenEnumerator::kInheritsSecurityToken);
- code_entries_.Add(entry);
- return entry;
-}
-
-
-CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
- int args_count) {
- CodeEntry* entry = new CodeEntry(tag,
- "args_count: ",
- GetName(args_count),
- TokenEnumerator::kInheritsSecurityToken);
- code_entries_.Add(entry);
- return entry;
-}
-
-
void CpuProfilesCollection::AddPathToCurrentProfiles(
const Vector<CodeEntry*>& path) {
// As starting / stopping profiles is rare relatively to this
}
+CodeEntry* CpuProfilesCollection::NewCodeEntry(
+ Logger::LogEventsAndTags tag,
+ const char* name,
+ int security_token_id,
+ const char* name_prefix,
+ const char* resource_name,
+ int line_number) {
+ CodeEntry* code_entry = new CodeEntry(tag,
+ name,
+ security_token_id,
+ name_prefix,
+ resource_name,
+ line_number);
+ code_entries_.Add(code_entry);
+ return code_entry;
+}
+
+
void SampleRateCalculator::Tick() {
if (--wall_time_query_countdown_ == 0)
UpdateMeasurements(OS::TimeCurrentMillis());
public:
// CodeEntry doesn't own name strings, just references them.
INLINE(CodeEntry(Logger::LogEventsAndTags tag,
- const char* name_prefix,
const char* name,
int security_token_id = TokenEnumerator::kNoSecurityToken,
+ const char* name_prefix = CodeEntry::kEmptyNamePrefix,
const char* resource_name = CodeEntry::kEmptyResourceName,
int line_number = v8::CpuProfileNode::kNoLineNumberInfo));
~CodeEntry();
const char* GetName(int args_count) {
return function_and_resource_names_.GetName(args_count);
}
+ const char* GetFunctionName(Name* name) {
+ return function_and_resource_names_.GetFunctionName(name);
+ }
+ const char* GetFunctionName(const char* name) {
+ return function_and_resource_names_.GetFunctionName(name);
+ }
CpuProfile* GetProfile(int security_token_id, unsigned uid);
bool IsLastProfile(const char* title);
void RemoveProfile(CpuProfile* profile);
bool HasDetachedProfiles() { return detached_profiles_.length() > 0; }
- CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
- Name* name, String* resource_name, int line_number);
- CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, const char* name);
- CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
- const char* name_prefix, Name* name);
- CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, int args_count);
- CodeEntry* NewCodeEntry(int security_token_id);
+ CodeEntry* NewCodeEntry(
+ Logger::LogEventsAndTags tag,
+ const char* name,
+ int security_token_id = TokenEnumerator::kNoSecurityToken,
+ const char* name_prefix = CodeEntry::kEmptyNamePrefix,
+ const char* resource_name = CodeEntry::kEmptyResourceName,
+ int line_number = v8::CpuProfileNode::kNoLineNumberInfo);
// Called from profile generator thread.
void AddPathToCurrentProfiles(const Vector<CodeEntry*>& path);
static const int kMaxSimultaneousProfiles = 100;
private:
- const char* GetFunctionName(Name* name) {
- return function_and_resource_names_.GetFunctionName(name);
- }
- const char* GetFunctionName(const char* name) {
- return function_and_resource_names_.GetFunctionName(name);
- }
int GetProfileIndex(unsigned uid);
List<CpuProfile*>* GetProfilesList(int security_token_id);
int TokenToIndex(int security_token_id);
#include "v8.h"
#include "cpu-profiler-inl.h"
#include "cctest.h"
+#include "platform.h"
#include "utils.h"
#include "../include/v8-profiler.h"
#undef V8_DISABLE_DEPRECATIONS
} // namespace
+
+i::Code* CreateCode(LocalContext* env) {
+ static int counter = 0;
+ i::EmbeddedVector<char, 256> script;
+ i::EmbeddedVector<char, 32> name;
+
+ i::OS::SNPrintF(name, "function_%d", ++counter);
+ const char* name_start = name.start();
+ i::OS::SNPrintF(script,
+ "function %s() {\n"
+ "var counter = 0;\n"
+ "for (var i = 0; i < %d; ++i) counter += i;\n"
+ "return '%s_' + counter;\n"
+ "}\n"
+ "%s();\n", name_start, counter, name_start, name_start);
+ CompileRun(script.start());
+ i::Handle<i::JSFunction> fun = v8::Utils::OpenHandle(
+ *v8::Local<v8::Function>::Cast(
+ (*env)->Global()->Get(v8_str(name_start))));
+ return fun->code();
+}
+
+
TEST(CodeEvents) {
CcTest::InitializeVM();
+ LocalContext env;
i::Isolate* isolate = i::Isolate::Current();
- i::Heap* heap = isolate->heap();
i::Factory* factory = isolate->factory();
TestSetup test_setup;
- CpuProfilesCollection profiles;
- profiles.StartProfiling("", 1, false);
- ProfileGenerator generator(&profiles);
- ProfilerEventsProcessor processor(&generator, &profiles);
+
+ i::HandleScope scope(isolate);
+
+ i::Code* aaa_code = CreateCode(&env);
+ i::Code* comment_code = CreateCode(&env);
+ i::Code* args5_code = CreateCode(&env);
+ i::Code* comment2_code = CreateCode(&env);
+ i::Code* moved_code = CreateCode(&env);
+ i::Code* args3_code = CreateCode(&env);
+ i::Code* args4_code = CreateCode(&env);
+
+ CpuProfilesCollection* profiles = new CpuProfilesCollection;
+ profiles->StartProfiling("", 1, false);
+ ProfileGenerator generator(profiles);
+ ProfilerEventsProcessor processor(&generator, profiles);
processor.Start();
+ CpuProfiler profiler(isolate, profiles, &generator, &processor);
// Enqueue code creation events.
- i::HandleScope scope(isolate);
const char* aaa_str = "aaa";
i::Handle<i::String> aaa_name = factory->NewStringFromAscii(
i::Vector<const char>(aaa_str, i::StrLength(aaa_str)));
- processor.CodeCreateEvent(i::Logger::FUNCTION_TAG,
- *aaa_name,
- heap->empty_string(),
- 0,
- ToAddress(0x1000),
- 0x100,
- ToAddress(0x10000),
- NULL);
- processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
- "bbb",
- ToAddress(0x1200),
- 0x80);
- processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
- processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
- "ddd",
- ToAddress(0x1400),
- 0x80);
- processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500));
- processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10);
- processor.CodeCreateEvent(i::Logger::STUB_TAG, 4, ToAddress(0x1605), 0x10);
+ profiler.CodeCreateEvent(i::Logger::FUNCTION_TAG, aaa_code, *aaa_name);
+ profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment_code, "comment");
+ profiler.CodeCreateEvent(i::Logger::STUB_TAG, args5_code, 5);
+ profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment2_code, "comment2");
+ profiler.CodeMoveEvent(comment2_code->address(), moved_code->address());
+ profiler.CodeCreateEvent(i::Logger::STUB_TAG, args3_code, 3);
+ profiler.CodeCreateEvent(i::Logger::STUB_TAG, args4_code, 4);
+
// Enqueue a tick event to enable code events processing.
- EnqueueTickSampleEvent(&processor, ToAddress(0x1000));
+ EnqueueTickSampleEvent(&processor, aaa_code->address());
processor.Stop();
processor.Join();
// Check the state of profile generator.
- CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000));
- CHECK_NE(NULL, entry1);
- CHECK_EQ(aaa_str, entry1->name());
- CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200));
- CHECK_NE(NULL, entry2);
- CHECK_EQ("bbb", entry2->name());
- CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300));
- CHECK_NE(NULL, entry3);
- 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);
- CHECK_EQ("ddd", entry4->name());
- CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600)));
+ CodeEntry* aaa = generator.code_map()->FindEntry(aaa_code->address());
+ CHECK_NE(NULL, aaa);
+ CHECK_EQ(aaa_str, aaa->name());
+
+ CodeEntry* comment = generator.code_map()->FindEntry(comment_code->address());
+ CHECK_NE(NULL, comment);
+ CHECK_EQ("comment", comment->name());
+
+ CodeEntry* args5 = generator.code_map()->FindEntry(args5_code->address());
+ CHECK_NE(NULL, args5);
+ CHECK_EQ("5", args5->name());
+
+ CHECK_EQ(NULL, generator.code_map()->FindEntry(comment2_code->address()));
+
+ CodeEntry* comment2 = generator.code_map()->FindEntry(moved_code->address());
+ CHECK_NE(NULL, comment2);
+ CHECK_EQ("comment2", comment2->name());
}
TEST(TickEvents) {
TestSetup test_setup;
- CpuProfilesCollection profiles;
- profiles.StartProfiling("", 1, false);
- ProfileGenerator generator(&profiles);
- ProfilerEventsProcessor processor(&generator, &profiles);
- processor.Start();
+ LocalContext env;
+ i::Isolate* isolate = i::Isolate::Current();
+ i::HandleScope scope(isolate);
- processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
- "bbb",
- ToAddress(0x1200),
- 0x80);
- processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
- processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
- "ddd",
- ToAddress(0x1400),
- 0x80);
- EnqueueTickSampleEvent(&processor, ToAddress(0x1210));
- EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220));
- EnqueueTickSampleEvent(&processor,
- ToAddress(0x1404),
- ToAddress(0x1305),
- ToAddress(0x1230));
+ i::Code* frame1_code = CreateCode(&env);
+ i::Code* frame2_code = CreateCode(&env);
+ i::Code* frame3_code = CreateCode(&env);
+
+ CpuProfilesCollection* profiles = new CpuProfilesCollection;
+ profiles->StartProfiling("", 1, false);
+ ProfileGenerator generator(profiles);
+ ProfilerEventsProcessor processor(&generator, profiles);
+ processor.Start();
+ CpuProfiler profiler(isolate, profiles, &generator, &processor);
+
+ profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame1_code, "bbb");
+ profiler.CodeCreateEvent(i::Logger::STUB_TAG, frame2_code, 5);
+ profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame3_code, "ddd");
+
+ EnqueueTickSampleEvent(&processor, frame1_code->instruction_start());
+ EnqueueTickSampleEvent(
+ &processor,
+ frame2_code->instruction_start() + frame2_code->ExecutableSize() / 2,
+ frame1_code->instruction_start() + frame2_code->ExecutableSize() / 2);
+ EnqueueTickSampleEvent(
+ &processor,
+ frame3_code->instruction_end() - 1,
+ frame2_code->instruction_end() - 1,
+ frame1_code->instruction_end() - 1);
processor.Stop();
processor.Join();
CpuProfile* profile =
- profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
+ profiles->StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
CHECK_NE(NULL, profile);
// Check call trees.
// Long stacks (exceeding max frames limit) must not be erased.
TEST(Issue1398) {
TestSetup test_setup;
- CpuProfilesCollection profiles;
- profiles.StartProfiling("", 1, false);
- ProfileGenerator generator(&profiles);
- ProfilerEventsProcessor processor(&generator, &profiles);
+ LocalContext env;
+ i::Isolate* isolate = i::Isolate::Current();
+ i::HandleScope scope(isolate);
+
+ i::Code* code = CreateCode(&env);
+
+ CpuProfilesCollection* profiles = new CpuProfilesCollection;
+ profiles->StartProfiling("", 1, false);
+ ProfileGenerator generator(profiles);
+ ProfilerEventsProcessor processor(&generator, profiles);
processor.Start();
+ CpuProfiler profiler(isolate, profiles, &generator, &processor);
- processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
- "bbb",
- ToAddress(0x1200),
- 0x80);
+ profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb");
i::TickSample* sample = processor.TickSampleEvent();
- sample->pc = ToAddress(0x1200);
+ sample->pc = code->address();
sample->tos = 0;
sample->frames_count = i::TickSample::kMaxFramesCount;
for (int i = 0; i < sample->frames_count; ++i) {
- sample->stack[i] = ToAddress(0x1200);
+ sample->stack[i] = code->address();
}
processor.Stop();
processor.Join();
CpuProfile* profile =
- profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
+ profiles->StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
CHECK_NE(NULL, profile);
int actual_depth = 0;
TEST(ProfileNodeFindOrAddChild) {
ProfileTree tree;
ProfileNode node(&tree, NULL);
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
ProfileNode* childNode1 = node.FindOrAddChild(&entry1);
CHECK_NE(NULL, childNode1);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
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");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
ProfileNode* childNode3 = node.FindOrAddChild(&entry3);
CHECK_NE(NULL, childNode3);
CHECK_NE(childNode1, childNode3);
TEST(ProfileNodeFindOrAddChildForSameFunction) {
- const char* empty = "";
const char* aaa = "aaa";
ProfileTree tree;
ProfileNode node(&tree, NULL);
- CodeEntry entry1(i::Logger::FUNCTION_TAG, empty, aaa);
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, aaa);
ProfileNode* childNode1 = node.FindOrAddChild(&entry1);
CHECK_NE(NULL, childNode1);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
// The same function again.
- CodeEntry entry2(i::Logger::FUNCTION_TAG, empty, aaa);
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, aaa);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry2));
// Now with a different security token.
- CodeEntry entry3(i::Logger::FUNCTION_TAG, empty, aaa,
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, aaa,
TokenEnumerator::kNoSecurityToken + 1);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry3));
}
} // namespace
TEST(ProfileTreeAddPathFromStart) {
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
ProfileTree tree;
ProfileTreeTestHelper helper(&tree);
CHECK_EQ(NULL, helper.Walk(&entry1));
TEST(ProfileTreeAddPathFromEnd) {
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
ProfileTree tree;
ProfileTreeTestHelper helper(&tree);
CHECK_EQ(NULL, helper.Walk(&entry1));
CHECK_EQ(1, empty_tree.root()->total_ticks());
CHECK_EQ(1, empty_tree.root()->self_ticks());
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
CodeEntry* e1_path[] = {&entry1};
Vector<CodeEntry*> e1_path_vec(
e1_path, sizeof(e1_path) / sizeof(e1_path[0]));
CHECK_EQ(1, node1->total_ticks());
CHECK_EQ(1, node1->self_ticks());
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
CodeEntry* e1_e2_path[] = {&entry1, &entry2};
Vector<CodeEntry*> e1_e2_path_vec(
e1_e2_path, sizeof(e1_e2_path) / sizeof(e1_e2_path[0]));
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");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
CodeEntry* e3_path[] = {&entry3};
Vector<CodeEntry*> e3_path_vec(
e3_path, sizeof(e3_path) / sizeof(e3_path[0]));
TEST(ProfileTreeFilteredClone) {
ProfileTree source_tree;
const int token0 = 0, token1 = 1, token2 = 2;
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", token0);
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", token1);
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", token0);
- CodeEntry entry4(i::Logger::FUNCTION_TAG, "", "ddd",
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa", token0);
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb", token1);
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc", token0);
+ CodeEntry entry4(i::Logger::FUNCTION_TAG, "ddd",
TokenEnumerator::kInheritsSecurityToken);
{
TEST(CodeMapAddCode) {
CodeMap code_map;
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
- CodeEntry entry4(i::Logger::FUNCTION_TAG, "", "ddd");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
+ CodeEntry entry4(i::Logger::FUNCTION_TAG, "ddd");
code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
code_map.AddCode(ToAddress(0x1900), &entry3, 0x50);
TEST(CodeMapMoveAndDeleteCode) {
CodeMap code_map;
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500)));
code_map.MoveCode(ToAddress(0x1500), ToAddress(0x1700)); // Deprecate bbb.
CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1500)));
CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1700)));
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
code_map.AddCode(ToAddress(0x1750), &entry3, 0x100);
CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1700)));
CHECK_EQ(&entry3, code_map.FindEntry(ToAddress(0x1750)));