blob: b76846b97222a1099799d98fe44b614b1b69753a [file] [log] [blame]
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001// 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"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00008#include "../include/v8-profiler.h"
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00009
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000010using i::CodeEntry;
lrn@chromium.org25156de2010-04-06 13:10:27 +000011using i::CpuProfile;
vegorov@chromium.org26c16f82010-08-11 13:41:03 +000012using i::CpuProfiler;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000013using i::CpuProfilesCollection;
14using i::ProfileGenerator;
15using i::ProfileNode;
16using i::ProfilerEventsProcessor;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000017using i::TokenEnumerator;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000018
19
20TEST(StartStop) {
21 CpuProfilesCollection profiles;
22 ProfileGenerator generator(&profiles);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000023 ProfilerEventsProcessor processor(&generator);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000024 processor.Start();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000025 processor.Stop();
26 processor.Join();
27}
28
29static v8::Persistent<v8::Context> env;
30
31static void InitializeVM() {
32 if (env.IsEmpty()) env = v8::Context::New();
33 v8::HandleScope scope;
34 env->Enter();
35}
36
37static inline i::Address ToAddress(int n) {
38 return reinterpret_cast<i::Address>(n);
39}
40
mmassi@chromium.org49a44672012-12-04 13:52:03 +000041static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
42 i::Address frame1,
43 i::Address frame2 = NULL,
44 i::Address frame3 = NULL) {
45 i::TickSample* sample = proc->TickSampleEvent();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000046 sample->pc = frame1;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000047 sample->tos = frame1;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000048 sample->frames_count = 0;
49 if (frame2 != NULL) {
50 sample->stack[0] = frame2;
51 sample->frames_count = 1;
52 }
53 if (frame3 != NULL) {
54 sample->stack[1] = frame3;
55 sample->frames_count = 2;
56 }
57}
58
ager@chromium.org357bf652010-04-12 11:30:10 +000059namespace {
60
61class TestSetup {
62 public:
63 TestSetup()
64 : old_flag_prof_browser_mode_(i::FLAG_prof_browser_mode) {
65 i::FLAG_prof_browser_mode = false;
66 }
67
68 ~TestSetup() {
69 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_;
70 }
71
72 private:
73 bool old_flag_prof_browser_mode_;
74};
75
76} // namespace
77
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000078TEST(CodeEvents) {
79 InitializeVM();
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000080 i::Isolate* isolate = i::Isolate::Current();
81 i::Heap* heap = isolate->heap();
82 i::Factory* factory = isolate->factory();
ager@chromium.org357bf652010-04-12 11:30:10 +000083 TestSetup test_setup;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000084 CpuProfilesCollection profiles;
lrn@chromium.org25156de2010-04-06 13:10:27 +000085 profiles.StartProfiling("", 1);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000086 ProfileGenerator generator(&profiles);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000087 ProfilerEventsProcessor processor(&generator);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000088 processor.Start();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000089
90 // Enqueue code creation events.
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000091 i::HandleScope scope(isolate);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000092 const char* aaa_str = "aaa";
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000093 i::Handle<i::String> aaa_name = factory->NewStringFromAscii(
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +000094 i::Vector<const char>(aaa_str, i::StrLength(aaa_str)));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000095 processor.CodeCreateEvent(i::Logger::FUNCTION_TAG,
96 *aaa_name,
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000097 heap->empty_string(),
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000098 0,
99 ToAddress(0x1000),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000100 0x100,
101 ToAddress(0x10000));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000102 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
103 "bbb",
104 ToAddress(0x1200),
105 0x80);
106 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
107 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
108 "ddd",
109 ToAddress(0x1400),
110 0x80);
111 processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500));
112 processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10);
lrn@chromium.org34e60782011-09-15 07:25:40 +0000113 processor.CodeCreateEvent(i::Logger::STUB_TAG, 4, ToAddress(0x1605), 0x10);
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000114 // Enqueue a tick event to enable code events processing.
115 EnqueueTickSampleEvent(&processor, ToAddress(0x1000));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000116
117 processor.Stop();
118 processor.Join();
119
120 // Check the state of profile generator.
121 CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000));
122 CHECK_NE(NULL, entry1);
123 CHECK_EQ(aaa_str, entry1->name());
124 CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200));
125 CHECK_NE(NULL, entry2);
126 CHECK_EQ("bbb", entry2->name());
127 CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300));
128 CHECK_NE(NULL, entry3);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000129 CHECK_EQ("5", entry3->name());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000130 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400)));
131 CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500));
132 CHECK_NE(NULL, entry4);
133 CHECK_EQ("ddd", entry4->name());
134 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600)));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000135}
136
137
138template<typename T>
139static int CompareProfileNodes(const T* p1, const T* p2) {
140 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name());
141}
142
143TEST(TickEvents) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000144 TestSetup test_setup;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000145 CpuProfilesCollection profiles;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000146 profiles.StartProfiling("", 1);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000147 ProfileGenerator generator(&profiles);
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000148 ProfilerEventsProcessor processor(&generator);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000149 processor.Start();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000150
151 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
152 "bbb",
153 ToAddress(0x1200),
154 0x80);
155 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
156 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
157 "ddd",
158 ToAddress(0x1400),
159 0x80);
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000160 EnqueueTickSampleEvent(&processor, ToAddress(0x1210));
161 EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220));
162 EnqueueTickSampleEvent(&processor,
163 ToAddress(0x1404),
164 ToAddress(0x1305),
165 ToAddress(0x1230));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000166
167 processor.Stop();
168 processor.Join();
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000169 CpuProfile* profile =
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000170 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000171 CHECK_NE(NULL, profile);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000172
173 // Check call trees.
lrn@chromium.org25156de2010-04-06 13:10:27 +0000174 const i::List<ProfileNode*>* top_down_root_children =
175 profile->top_down()->root()->children();
176 CHECK_EQ(1, top_down_root_children->length());
177 CHECK_EQ("bbb", top_down_root_children->last()->entry()->name());
178 const i::List<ProfileNode*>* top_down_bbb_children =
179 top_down_root_children->last()->children();
180 CHECK_EQ(1, top_down_bbb_children->length());
181 CHECK_EQ("5", top_down_bbb_children->last()->entry()->name());
182 const i::List<ProfileNode*>* top_down_stub_children =
183 top_down_bbb_children->last()->children();
184 CHECK_EQ(1, top_down_stub_children->length());
185 CHECK_EQ("ddd", top_down_stub_children->last()->entry()->name());
186 const i::List<ProfileNode*>* top_down_ddd_children =
187 top_down_stub_children->last()->children();
188 CHECK_EQ(0, top_down_ddd_children->length());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000189
lrn@chromium.org25156de2010-04-06 13:10:27 +0000190 const i::List<ProfileNode*>* bottom_up_root_children_unsorted =
191 profile->bottom_up()->root()->children();
192 CHECK_EQ(3, bottom_up_root_children_unsorted->length());
193 i::List<ProfileNode*> bottom_up_root_children(3);
194 bottom_up_root_children.AddAll(*bottom_up_root_children_unsorted);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000195 bottom_up_root_children.Sort(&CompareProfileNodes);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000196 CHECK_EQ("5", bottom_up_root_children[0]->entry()->name());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000197 CHECK_EQ("bbb", bottom_up_root_children[1]->entry()->name());
198 CHECK_EQ("ddd", bottom_up_root_children[2]->entry()->name());
lrn@chromium.org25156de2010-04-06 13:10:27 +0000199 const i::List<ProfileNode*>* bottom_up_stub_children =
200 bottom_up_root_children[0]->children();
201 CHECK_EQ(1, bottom_up_stub_children->length());
202 CHECK_EQ("bbb", bottom_up_stub_children->last()->entry()->name());
203 const i::List<ProfileNode*>* bottom_up_bbb_children =
204 bottom_up_root_children[1]->children();
205 CHECK_EQ(0, bottom_up_bbb_children->length());
206 const i::List<ProfileNode*>* bottom_up_ddd_children =
207 bottom_up_root_children[2]->children();
208 CHECK_EQ(1, bottom_up_ddd_children->length());
209 CHECK_EQ("5", bottom_up_ddd_children->last()->entry()->name());
210 const i::List<ProfileNode*>* bottom_up_ddd_stub_children =
211 bottom_up_ddd_children->last()->children();
212 CHECK_EQ(1, bottom_up_ddd_stub_children->length());
213 CHECK_EQ("bbb", bottom_up_ddd_stub_children->last()->entry()->name());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000214}
lrn@chromium.org25156de2010-04-06 13:10:27 +0000215
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000216
217// http://crbug/51594
218// This test must not crash.
219TEST(CrashIfStoppingLastNonExistentProfile) {
220 InitializeVM();
221 TestSetup test_setup;
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000222 CpuProfiler::SetUp();
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000223 CpuProfiler::StartProfiling("1");
224 CpuProfiler::StopProfiling("2");
225 CpuProfiler::StartProfiling("1");
226 CpuProfiler::StopProfiling("");
227 CpuProfiler::TearDown();
228}
229
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000230
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000231// http://code.google.com/p/v8/issues/detail?id=1398
232// Long stacks (exceeding max frames limit) must not be erased.
233TEST(Issue1398) {
234 TestSetup test_setup;
235 CpuProfilesCollection profiles;
236 profiles.StartProfiling("", 1);
237 ProfileGenerator generator(&profiles);
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000238 ProfilerEventsProcessor processor(&generator);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000239 processor.Start();
240
241 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
242 "bbb",
243 ToAddress(0x1200),
244 0x80);
245
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000246 i::TickSample* sample = processor.TickSampleEvent();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000247 sample->pc = ToAddress(0x1200);
248 sample->tos = 0;
249 sample->frames_count = i::TickSample::kMaxFramesCount;
250 for (int i = 0; i < sample->frames_count; ++i) {
251 sample->stack[i] = ToAddress(0x1200);
252 }
253
254 processor.Stop();
255 processor.Join();
256 CpuProfile* profile =
257 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
258 CHECK_NE(NULL, profile);
259
260 int actual_depth = 0;
261 const ProfileNode* node = profile->top_down()->root();
262 while (node->children()->length() > 0) {
263 node = node->children()->last();
264 ++actual_depth;
265 }
266
267 CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth); // +1 for PC.
268}
269
270
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000271TEST(DeleteAllCpuProfiles) {
272 InitializeVM();
273 TestSetup test_setup;
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000274 CpuProfiler::SetUp();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000275 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
276 CpuProfiler::DeleteAllProfiles();
277 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
278
279 CpuProfiler::StartProfiling("1");
280 CpuProfiler::StopProfiling("1");
281 CHECK_EQ(1, CpuProfiler::GetProfilesCount());
282 CpuProfiler::DeleteAllProfiles();
283 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
284 CpuProfiler::StartProfiling("1");
285 CpuProfiler::StartProfiling("2");
286 CpuProfiler::StopProfiling("2");
287 CpuProfiler::StopProfiling("1");
288 CHECK_EQ(2, CpuProfiler::GetProfilesCount());
289 CpuProfiler::DeleteAllProfiles();
290 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
291
292 // Test profiling cancellation by the 'delete' command.
293 CpuProfiler::StartProfiling("1");
294 CpuProfiler::StartProfiling("2");
295 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
296 CpuProfiler::DeleteAllProfiles();
297 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
298
299 CpuProfiler::TearDown();
300}
301
302
303TEST(DeleteCpuProfile) {
304 v8::HandleScope scope;
305 LocalContext env;
306
307 CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
308 v8::Local<v8::String> name1 = v8::String::New("1");
309 v8::CpuProfiler::StartProfiling(name1);
310 const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
311 CHECK_NE(NULL, p1);
312 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
313 unsigned uid1 = p1->GetUid();
314 CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
315 const_cast<v8::CpuProfile*>(p1)->Delete();
316 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
317 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
318
319 v8::Local<v8::String> name2 = v8::String::New("2");
320 v8::CpuProfiler::StartProfiling(name2);
321 const v8::CpuProfile* p2 = v8::CpuProfiler::StopProfiling(name2);
322 CHECK_NE(NULL, p2);
323 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
324 unsigned uid2 = p2->GetUid();
325 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
326 CHECK_EQ(p2, v8::CpuProfiler::FindProfile(uid2));
327 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
328 v8::Local<v8::String> name3 = v8::String::New("3");
329 v8::CpuProfiler::StartProfiling(name3);
330 const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
331 CHECK_NE(NULL, p3);
332 CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
333 unsigned uid3 = p3->GetUid();
334 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
335 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
336 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
337 const_cast<v8::CpuProfile*>(p2)->Delete();
338 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
339 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
340 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
341 const_cast<v8::CpuProfile*>(p3)->Delete();
342 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
343 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
344 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
345 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
346}
347
348
349TEST(DeleteCpuProfileDifferentTokens) {
350 v8::HandleScope scope;
351 LocalContext env;
352
353 CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
354 v8::Local<v8::String> name1 = v8::String::New("1");
355 v8::CpuProfiler::StartProfiling(name1);
356 const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
357 CHECK_NE(NULL, p1);
358 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
359 unsigned uid1 = p1->GetUid();
360 CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
361 v8::Local<v8::String> token1 = v8::String::New("token1");
362 const v8::CpuProfile* p1_t1 = v8::CpuProfiler::FindProfile(uid1, token1);
363 CHECK_NE(NULL, p1_t1);
364 CHECK_NE(p1, p1_t1);
365 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
366 const_cast<v8::CpuProfile*>(p1)->Delete();
367 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
368 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
369 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1, token1));
370 const_cast<v8::CpuProfile*>(p1_t1)->Delete();
371 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
372
373 v8::Local<v8::String> name2 = v8::String::New("2");
374 v8::CpuProfiler::StartProfiling(name2);
375 v8::Local<v8::String> token2 = v8::String::New("token2");
376 const v8::CpuProfile* p2_t2 = v8::CpuProfiler::StopProfiling(name2, token2);
377 CHECK_NE(NULL, p2_t2);
378 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
379 unsigned uid2 = p2_t2->GetUid();
380 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
381 const v8::CpuProfile* p2 = v8::CpuProfiler::FindProfile(uid2);
382 CHECK_NE(p2_t2, p2);
383 v8::Local<v8::String> name3 = v8::String::New("3");
384 v8::CpuProfiler::StartProfiling(name3);
385 const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
386 CHECK_NE(NULL, p3);
387 CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
388 unsigned uid3 = p3->GetUid();
389 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
390 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
391 const_cast<v8::CpuProfile*>(p2_t2)->Delete();
392 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
393 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
394 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
395 const_cast<v8::CpuProfile*>(p2)->Delete();
396 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
397 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
398 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
399 const_cast<v8::CpuProfile*>(p3)->Delete();
400 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
401 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
402}