OLD | NEW |
(Empty) | |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // |
| 3 // Tests of profiles generator and utilities. |
| 4 |
| 5 #include "v8.h" |
| 6 #include "cpu-profiler-inl.h" |
| 7 #include "cctest.h" |
| 8 |
| 9 namespace i = v8::internal; |
| 10 |
| 11 using i::CodeEntry; |
| 12 using i::CpuProfilesCollection; |
| 13 using i::ProfileGenerator; |
| 14 using i::ProfileNode; |
| 15 using i::ProfilerEventsProcessor; |
| 16 |
| 17 |
| 18 TEST(StartStop) { |
| 19 CpuProfilesCollection profiles; |
| 20 ProfileGenerator generator(&profiles); |
| 21 ProfilerEventsProcessor processor(&generator); |
| 22 processor.Start(); |
| 23 while (!processor.running()) { |
| 24 i::Thread::YieldCPU(); |
| 25 } |
| 26 processor.Stop(); |
| 27 processor.Join(); |
| 28 } |
| 29 |
| 30 static v8::Persistent<v8::Context> env; |
| 31 |
| 32 static void InitializeVM() { |
| 33 if (env.IsEmpty()) env = v8::Context::New(); |
| 34 v8::HandleScope scope; |
| 35 env->Enter(); |
| 36 } |
| 37 |
| 38 static inline i::Address ToAddress(int n) { |
| 39 return reinterpret_cast<i::Address>(n); |
| 40 } |
| 41 |
| 42 static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc, |
| 43 i::Address frame1, |
| 44 i::Address frame2 = NULL, |
| 45 i::Address frame3 = NULL) { |
| 46 i::TickSample* sample = proc->TickSampleEvent(); |
| 47 sample->pc = frame1; |
| 48 sample->function = frame1; |
| 49 sample->frames_count = 0; |
| 50 if (frame2 != NULL) { |
| 51 sample->stack[0] = frame2; |
| 52 sample->frames_count = 1; |
| 53 } |
| 54 if (frame3 != NULL) { |
| 55 sample->stack[1] = frame3; |
| 56 sample->frames_count = 2; |
| 57 } |
| 58 } |
| 59 |
| 60 TEST(CodeEvents) { |
| 61 InitializeVM(); |
| 62 CpuProfilesCollection profiles; |
| 63 profiles.AddProfile(0); |
| 64 ProfileGenerator generator(&profiles); |
| 65 ProfilerEventsProcessor processor(&generator); |
| 66 processor.Start(); |
| 67 processor.SetUpSamplesProducer(); |
| 68 while (!processor.running()) { |
| 69 i::Thread::YieldCPU(); |
| 70 } |
| 71 |
| 72 // Enqueue code creation events. |
| 73 i::HandleScope scope; |
| 74 const char* aaa_str = "aaa"; |
| 75 i::Handle<i::String> aaa_name = i::Factory::NewStringFromAscii( |
| 76 i::Vector<const char>(aaa_str, strlen(aaa_str))); |
| 77 processor.CodeCreateEvent(i::Logger::FUNCTION_TAG, |
| 78 *aaa_name, |
| 79 i::Heap::empty_string(), |
| 80 0, |
| 81 ToAddress(0x1000), |
| 82 0x100); |
| 83 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 84 "bbb", |
| 85 ToAddress(0x1200), |
| 86 0x80); |
| 87 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10); |
| 88 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 89 "ddd", |
| 90 ToAddress(0x1400), |
| 91 0x80); |
| 92 processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500)); |
| 93 processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10); |
| 94 processor.CodeDeleteEvent(ToAddress(0x1600)); |
| 95 processor.FunctionCreateEvent(ToAddress(0x1700), ToAddress(0x1000)); |
| 96 // Enqueue a tick event to enable code events processing. |
| 97 EnqueueTickSampleEvent(&processor, ToAddress(0x1000)); |
| 98 |
| 99 processor.Stop(); |
| 100 processor.Join(); |
| 101 |
| 102 // Check the state of profile generator. |
| 103 CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000)); |
| 104 CHECK_NE(NULL, entry1); |
| 105 CHECK_EQ(aaa_str, entry1->name()); |
| 106 CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200)); |
| 107 CHECK_NE(NULL, entry2); |
| 108 CHECK_EQ("bbb", entry2->name()); |
| 109 CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300)); |
| 110 CHECK_NE(NULL, entry3); |
| 111 CHECK_EQ("args_count: 5", entry3->name()); |
| 112 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400))); |
| 113 CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500)); |
| 114 CHECK_NE(NULL, entry4); |
| 115 CHECK_EQ("ddd", entry4->name()); |
| 116 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600))); |
| 117 CodeEntry* entry5 = generator.code_map()->FindEntry(ToAddress(0x1700)); |
| 118 CHECK_NE(NULL, entry5); |
| 119 CHECK_EQ(aaa_str, entry5->name()); |
| 120 |
| 121 processor.TearDownSamplesProducer(); |
| 122 } |
| 123 |
| 124 |
| 125 template<typename T> |
| 126 static int CompareProfileNodes(const T* p1, const T* p2) { |
| 127 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name()); |
| 128 } |
| 129 |
| 130 TEST(TickEvents) { |
| 131 CpuProfilesCollection profiles; |
| 132 profiles.AddProfile(0); |
| 133 ProfileGenerator generator(&profiles); |
| 134 ProfilerEventsProcessor processor(&generator); |
| 135 processor.Start(); |
| 136 processor.SetUpSamplesProducer(); |
| 137 while (!processor.running()) { |
| 138 i::Thread::YieldCPU(); |
| 139 } |
| 140 |
| 141 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 142 "bbb", |
| 143 ToAddress(0x1200), |
| 144 0x80); |
| 145 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10); |
| 146 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 147 "ddd", |
| 148 ToAddress(0x1400), |
| 149 0x80); |
| 150 EnqueueTickSampleEvent(&processor, ToAddress(0x1210)); |
| 151 EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220)); |
| 152 EnqueueTickSampleEvent(&processor, |
| 153 ToAddress(0x1404), |
| 154 ToAddress(0x1305), |
| 155 ToAddress(0x1230)); |
| 156 |
| 157 processor.Stop(); |
| 158 processor.Join(); |
| 159 |
| 160 // Check call trees. |
| 161 i::List<ProfileNode*> top_down_root_children; |
| 162 profiles.profile()->top_down()->root()->GetChildren(&top_down_root_children); |
| 163 CHECK_EQ(1, top_down_root_children.length()); |
| 164 CHECK_EQ("bbb", top_down_root_children.last()->entry()->name()); |
| 165 i::List<ProfileNode*> top_down_bbb_children; |
| 166 top_down_root_children.last()->GetChildren(&top_down_bbb_children); |
| 167 CHECK_EQ(1, top_down_bbb_children.length()); |
| 168 CHECK_EQ("args_count: 5", top_down_bbb_children.last()->entry()->name()); |
| 169 i::List<ProfileNode*> top_down_stub_children; |
| 170 top_down_bbb_children.last()->GetChildren(&top_down_stub_children); |
| 171 CHECK_EQ(1, top_down_stub_children.length()); |
| 172 CHECK_EQ("ddd", top_down_stub_children.last()->entry()->name()); |
| 173 i::List<ProfileNode*> top_down_ddd_children; |
| 174 top_down_stub_children.last()->GetChildren(&top_down_ddd_children); |
| 175 CHECK_EQ(0, top_down_ddd_children.length()); |
| 176 |
| 177 i::List<ProfileNode*> bottom_up_root_children; |
| 178 profiles.profile()->bottom_up()->root()->GetChildren( |
| 179 &bottom_up_root_children); |
| 180 CHECK_EQ(3, bottom_up_root_children.length()); |
| 181 bottom_up_root_children.Sort(&CompareProfileNodes); |
| 182 CHECK_EQ("args_count: 5", bottom_up_root_children[0]->entry()->name()); |
| 183 CHECK_EQ("bbb", bottom_up_root_children[1]->entry()->name()); |
| 184 CHECK_EQ("ddd", bottom_up_root_children[2]->entry()->name()); |
| 185 i::List<ProfileNode*> bottom_up_stub_children; |
| 186 bottom_up_root_children[0]->GetChildren(&bottom_up_stub_children); |
| 187 CHECK_EQ(1, bottom_up_stub_children.length()); |
| 188 CHECK_EQ("bbb", bottom_up_stub_children.last()->entry()->name()); |
| 189 i::List<ProfileNode*> bottom_up_bbb_children; |
| 190 bottom_up_root_children[1]->GetChildren(&bottom_up_bbb_children); |
| 191 CHECK_EQ(0, bottom_up_bbb_children.length()); |
| 192 i::List<ProfileNode*> bottom_up_ddd_children; |
| 193 bottom_up_root_children[2]->GetChildren(&bottom_up_ddd_children); |
| 194 CHECK_EQ(1, bottom_up_ddd_children.length()); |
| 195 CHECK_EQ("args_count: 5", bottom_up_ddd_children.last()->entry()->name()); |
| 196 i::List<ProfileNode*> bottom_up_ddd_stub_children; |
| 197 bottom_up_ddd_children.last()->GetChildren(&bottom_up_ddd_stub_children); |
| 198 CHECK_EQ(1, bottom_up_ddd_stub_children.length()); |
| 199 CHECK_EQ("bbb", bottom_up_ddd_stub_children.last()->entry()->name()); |
| 200 |
| 201 processor.TearDownSamplesProducer(); |
| 202 } |
OLD | NEW |