Add a few tests to ProfilerEventsProcessor.
authormikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Mar 2010 13:51:01 +0000 (13:51 +0000)
committermikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 19 Mar 2010 13:51:01 +0000 (13:51 +0000)
Review URL: http://codereview.chromium.org/1084009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4197 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/cpu-profiler.h
src/profile-generator.cc
src/profile-generator.h
test/cctest/SConscript
test/cctest/test-cpu-profiler.cc [new file with mode: 0644]
test/cctest/test-profile-generator.cc
tools/visual_studio/v8_cctest.vcproj
tools/visual_studio/v8_cctest_arm.vcproj
tools/visual_studio/v8_cctest_x64.vcproj

index f9bad4596ec557a766718ff7102a8ec4d95f15d8..ccfac5c5c7e5601115e44ffe83dab31c9a2670b5 100644 (file)
@@ -135,6 +135,7 @@ class ProfilerEventsProcessor : public Thread {
   // Thread control.
   virtual void Run();
   inline void Stop() { running_ = false; }
+  INLINE(bool running()) { return running_; }
 
   // Events adding methods. Called by VM threads.
   void CodeCreateEvent(Logger::LogEventsAndTags tag,
index 9d7c3461cd3eaa790de955389d94f97bd5a77fb8..7f020c5bb5b4f8a543b84eb09fe6cbcfe15e7ffc 100644 (file)
@@ -53,6 +53,15 @@ ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) {
 }
 
 
+void ProfileNode::GetChildren(List<ProfileNode*>* children) {
+  for (HashMap::Entry* p = children_.Start();
+       p != NULL;
+       p = children_.Next(p)) {
+    children->Add(reinterpret_cast<ProfileNode*>(p->value));
+  }
+}
+
+
 void ProfileNode::Print(int indent) {
   OS::Print("%4u %4u %*c %s\n",
             total_ticks_, self_ticks_,
index a16ea66f710dd75124dd90a08ed46f8f066c74ed..c0454cb821f6902b35f7e480023d2fab0bdd07e1 100644 (file)
@@ -64,9 +64,10 @@ class ProfileNode {
   INLINE(void IncrementSelfTicks()) { ++self_ticks_; }
   INLINE(void IncreaseTotalTicks(unsigned amount)) { total_ticks_ += amount; }
 
-  INLINE(CodeEntry* entry()) { return entry_; }
-  INLINE(unsigned total_ticks()) { return total_ticks_; }
-  INLINE(unsigned self_ticks()) { return self_ticks_; }
+  INLINE(CodeEntry* entry() const) { return entry_; }
+  INLINE(unsigned total_ticks() const) { return total_ticks_; }
+  INLINE(unsigned self_ticks() const) { return self_ticks_; }
+  void GetChildren(List<ProfileNode*>* children);
 
   void Print(int indent);
 
index 883cdeb0f5aecd1f5947f441331d90b275438aae..0d59b214e8c7ffe61dd604ca8d8a436d9caa8647 100644 (file)
@@ -42,6 +42,7 @@ SOURCES = {
     'test-circular-queue.cc',
     'test-compiler.cc',
     'test-conversions.cc',
+    'test-cpu-profiler.cc',
     'test-dataflow.cc',
     'test-debug.cc',
     'test-decls.cc',
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
new file mode 100644 (file)
index 0000000..bd966fa
--- /dev/null
@@ -0,0 +1,202 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+//
+// Tests of profiles generator and utilities.
+
+#include "v8.h"
+#include "cpu-profiler-inl.h"
+#include "cctest.h"
+
+namespace i = v8::internal;
+
+using i::CodeEntry;
+using i::CpuProfilesCollection;
+using i::ProfileGenerator;
+using i::ProfileNode;
+using i::ProfilerEventsProcessor;
+
+
+TEST(StartStop) {
+  CpuProfilesCollection profiles;
+  ProfileGenerator generator(&profiles);
+  ProfilerEventsProcessor processor(&generator);
+  processor.Start();
+  while (!processor.running()) {
+    i::Thread::YieldCPU();
+  }
+  processor.Stop();
+  processor.Join();
+}
+
+static v8::Persistent<v8::Context> env;
+
+static void InitializeVM() {
+  if (env.IsEmpty()) env = v8::Context::New();
+  v8::HandleScope scope;
+  env->Enter();
+}
+
+static inline i::Address ToAddress(int n) {
+  return reinterpret_cast<i::Address>(n);
+}
+
+static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
+                                   i::Address frame1,
+                                   i::Address frame2 = NULL,
+                                   i::Address frame3 = NULL) {
+  i::TickSample* sample = proc->TickSampleEvent();
+  sample->pc = frame1;
+  sample->function = frame1;
+  sample->frames_count = 0;
+  if (frame2 != NULL) {
+    sample->stack[0] = frame2;
+    sample->frames_count = 1;
+  }
+  if (frame3 != NULL) {
+    sample->stack[1] = frame3;
+    sample->frames_count = 2;
+  }
+}
+
+TEST(CodeEvents) {
+  InitializeVM();
+  CpuProfilesCollection profiles;
+  profiles.AddProfile(0);
+  ProfileGenerator generator(&profiles);
+  ProfilerEventsProcessor processor(&generator);
+  processor.Start();
+  processor.SetUpSamplesProducer();
+  while (!processor.running()) {
+    i::Thread::YieldCPU();
+  }
+
+  // Enqueue code creation events.
+  i::HandleScope scope;
+  const char* aaa_str = "aaa";
+  i::Handle<i::String> aaa_name = i::Factory::NewStringFromAscii(
+      i::Vector<const char>(aaa_str, strlen(aaa_str)));
+  processor.CodeCreateEvent(i::Logger::FUNCTION_TAG,
+                            *aaa_name,
+                            i::Heap::empty_string(),
+                            0,
+                            ToAddress(0x1000),
+                            0x100);
+  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.CodeDeleteEvent(ToAddress(0x1600));
+  processor.FunctionCreateEvent(ToAddress(0x1700), ToAddress(0x1000));
+  // Enqueue a tick event to enable code events processing.
+  EnqueueTickSampleEvent(&processor, ToAddress(0x1000));
+
+  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("args_count: 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* entry5 = generator.code_map()->FindEntry(ToAddress(0x1700));
+  CHECK_NE(NULL, entry5);
+  CHECK_EQ(aaa_str, entry5->name());
+
+  processor.TearDownSamplesProducer();
+}
+
+
+template<typename T>
+static int CompareProfileNodes(const T* p1, const T* p2) {
+  return strcmp((*p1)->entry()->name(), (*p2)->entry()->name());
+}
+
+TEST(TickEvents) {
+  CpuProfilesCollection profiles;
+  profiles.AddProfile(0);
+  ProfileGenerator generator(&profiles);
+  ProfilerEventsProcessor processor(&generator);
+  processor.Start();
+  processor.SetUpSamplesProducer();
+  while (!processor.running()) {
+    i::Thread::YieldCPU();
+  }
+
+  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));
+
+  processor.Stop();
+  processor.Join();
+
+  // Check call trees.
+  i::List<ProfileNode*> top_down_root_children;
+  profiles.profile()->top_down()->root()->GetChildren(&top_down_root_children);
+  CHECK_EQ(1, top_down_root_children.length());
+  CHECK_EQ("bbb", top_down_root_children.last()->entry()->name());
+  i::List<ProfileNode*> top_down_bbb_children;
+  top_down_root_children.last()->GetChildren(&top_down_bbb_children);
+  CHECK_EQ(1, top_down_bbb_children.length());
+  CHECK_EQ("args_count: 5", top_down_bbb_children.last()->entry()->name());
+  i::List<ProfileNode*> top_down_stub_children;
+  top_down_bbb_children.last()->GetChildren(&top_down_stub_children);
+  CHECK_EQ(1, top_down_stub_children.length());
+  CHECK_EQ("ddd", top_down_stub_children.last()->entry()->name());
+  i::List<ProfileNode*> top_down_ddd_children;
+  top_down_stub_children.last()->GetChildren(&top_down_ddd_children);
+  CHECK_EQ(0, top_down_ddd_children.length());
+
+  i::List<ProfileNode*> bottom_up_root_children;
+  profiles.profile()->bottom_up()->root()->GetChildren(
+      &bottom_up_root_children);
+  CHECK_EQ(3, bottom_up_root_children.length());
+  bottom_up_root_children.Sort(&CompareProfileNodes);
+  CHECK_EQ("args_count: 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());
+  i::List<ProfileNode*> bottom_up_stub_children;
+  bottom_up_root_children[0]->GetChildren(&bottom_up_stub_children);
+  CHECK_EQ(1, bottom_up_stub_children.length());
+  CHECK_EQ("bbb", bottom_up_stub_children.last()->entry()->name());
+  i::List<ProfileNode*> bottom_up_bbb_children;
+  bottom_up_root_children[1]->GetChildren(&bottom_up_bbb_children);
+  CHECK_EQ(0, bottom_up_bbb_children.length());
+  i::List<ProfileNode*> bottom_up_ddd_children;
+  bottom_up_root_children[2]->GetChildren(&bottom_up_ddd_children);
+  CHECK_EQ(1, bottom_up_ddd_children.length());
+  CHECK_EQ("args_count: 5", bottom_up_ddd_children.last()->entry()->name());
+  i::List<ProfileNode*> bottom_up_ddd_stub_children;
+  bottom_up_ddd_children.last()->GetChildren(&bottom_up_ddd_stub_children);
+  CHECK_EQ(1, bottom_up_ddd_stub_children.length());
+  CHECK_EQ("bbb", bottom_up_ddd_stub_children.last()->entry()->name());
+
+  processor.TearDownSamplesProducer();
+}
index fc4d603e61020cae6cb437521744ca5626a951c3..b63dd1267871c4a955b9670f324332466150e459 100644 (file)
@@ -412,9 +412,9 @@ TEST(RecordTickSample) {
   ProfileNode* node2 = top_down_test_helper.Walk(entry1, entry1);
   CHECK_NE(NULL, node2);
   CHECK_EQ(entry1, node2->entry());
-  // ProfileNode* node3 = top_down_test_helper.Walk(entry1, entry2, entry3);
-  // CHECK_NE(NULL, node3);
-  // CHECK_EQ(entry2, node3->entry());
+  ProfileNode* node3 = top_down_test_helper.Walk(entry1, entry2, entry3);
+  CHECK_NE(NULL, node3);
+  CHECK_EQ(entry3, node3->entry());
   ProfileNode* node4 = top_down_test_helper.Walk(entry1, entry3, entry1);
   CHECK_NE(NULL, node4);
   CHECK_EQ(entry1, node4->entry());
index 7d0c4fffa96f8770e96cff1f3bc8b974d97864dd..424d2262bd426d8bcd5dfe7a07e18feda2820ef3 100644 (file)
                        RelativePath="..\..\test\cctest\test-conversions.cc"
                        >
                </File>
+               <File
+                       RelativePath="..\..\test\cctest\test-cpu-profiler.cc"
+                       >
+               </File>
                <File
                        RelativePath="..\..\test\cctest\test-debug.cc"
                        >
index ee08b4fbf605c6d8b258b7003fbba16c4705dc7b..92f7fc3fb765c18f0becaaaadfee8442e8850a0f 100644 (file)
                        RelativePath="..\..\test\cctest\test-conversions.cc"
                        >
                </File>
+               <File
+                       RelativePath="..\..\test\cctest\test-cpu-profiler.cc"
+                       >
+               </File>
                <File
                        RelativePath="..\..\test\cctest\test-debug.cc"
                        >
index ee80c41eca367822573761a2bb9add4fb638f669..dea4d52b1b678e7f08ea93e5a2e9423aaf119fa2 100644 (file)
                        RelativePath="..\..\test\cctest\test-conversions.cc"
                        >
                </File>
+               <File
+                       RelativePath="..\..\test\cctest\test-cpu-profiler.cc"
+                       >
+               </File>
                <File
                        RelativePath="..\..\test\cctest\test-debug.cc"
                        >