blob: beb73c5a648f696c88ba9823ab9fc41f2c4736d3 [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
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00005#ifdef ENABLE_LOGGING_AND_PROFILING
lrn@chromium.org25156de2010-04-06 13:10:27 +00006
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00007#include "v8.h"
8#include "cpu-profiler-inl.h"
9#include "cctest.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000010#include "../include/v8-profiler.h"
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000011
12namespace i = v8::internal;
13
14using i::CodeEntry;
lrn@chromium.org25156de2010-04-06 13:10:27 +000015using i::CpuProfile;
vegorov@chromium.org26c16f82010-08-11 13:41:03 +000016using i::CpuProfiler;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000017using i::CpuProfilesCollection;
18using i::ProfileGenerator;
19using i::ProfileNode;
20using i::ProfilerEventsProcessor;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000021using i::TokenEnumerator;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000022
23
24TEST(StartStop) {
25 CpuProfilesCollection profiles;
26 ProfileGenerator generator(&profiles);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000027 ProfilerEventsProcessor processor(i::Isolate::Current(), &generator);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000028 processor.Start();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000029 processor.Stop();
30 processor.Join();
31}
32
33static v8::Persistent<v8::Context> env;
34
35static void InitializeVM() {
36 if (env.IsEmpty()) env = v8::Context::New();
37 v8::HandleScope scope;
38 env->Enter();
39}
40
41static inline i::Address ToAddress(int n) {
42 return reinterpret_cast<i::Address>(n);
43}
44
45static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
46 i::Address frame1,
47 i::Address frame2 = NULL,
48 i::Address frame3 = NULL) {
49 i::TickSample* sample = proc->TickSampleEvent();
50 sample->pc = frame1;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000051 sample->tos = frame1;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000052 sample->frames_count = 0;
53 if (frame2 != NULL) {
54 sample->stack[0] = frame2;
55 sample->frames_count = 1;
56 }
57 if (frame3 != NULL) {
58 sample->stack[1] = frame3;
59 sample->frames_count = 2;
60 }
61}
62
ager@chromium.org357bf652010-04-12 11:30:10 +000063namespace {
64
65class TestSetup {
66 public:
67 TestSetup()
68 : old_flag_prof_browser_mode_(i::FLAG_prof_browser_mode) {
69 i::FLAG_prof_browser_mode = false;
70 }
71
72 ~TestSetup() {
73 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_;
74 }
75
76 private:
77 bool old_flag_prof_browser_mode_;
78};
79
80} // namespace
81
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000082TEST(CodeEvents) {
83 InitializeVM();
ager@chromium.org357bf652010-04-12 11:30:10 +000084 TestSetup test_setup;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000085 CpuProfilesCollection profiles;
lrn@chromium.org25156de2010-04-06 13:10:27 +000086 profiles.StartProfiling("", 1);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000087 ProfileGenerator generator(&profiles);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000088 ProfilerEventsProcessor processor(i::Isolate::Current(), &generator);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000089 processor.Start();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000090
91 // Enqueue code creation events.
92 i::HandleScope scope;
93 const char* aaa_str = "aaa";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000094 i::Handle<i::String> aaa_name = FACTORY->NewStringFromAscii(
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +000095 i::Vector<const char>(aaa_str, i::StrLength(aaa_str)));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000096 processor.CodeCreateEvent(i::Logger::FUNCTION_TAG,
97 *aaa_name,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000098 HEAP->empty_string(),
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000099 0,
100 ToAddress(0x1000),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000101 0x100,
102 ToAddress(0x10000));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000103 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
104 "bbb",
105 ToAddress(0x1200),
106 0x80);
107 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
108 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
109 "ddd",
110 ToAddress(0x1400),
111 0x80);
112 processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500));
113 processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10);
114 processor.CodeDeleteEvent(ToAddress(0x1600));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000115 // Enqueue a tick event to enable code events processing.
116 EnqueueTickSampleEvent(&processor, ToAddress(0x1000));
117
118 processor.Stop();
119 processor.Join();
120
121 // Check the state of profile generator.
122 CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000));
123 CHECK_NE(NULL, entry1);
124 CHECK_EQ(aaa_str, entry1->name());
125 CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200));
126 CHECK_NE(NULL, entry2);
127 CHECK_EQ("bbb", entry2->name());
128 CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300));
129 CHECK_NE(NULL, entry3);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000130 CHECK_EQ("5", entry3->name());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000131 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400)));
132 CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500));
133 CHECK_NE(NULL, entry4);
134 CHECK_EQ("ddd", entry4->name());
135 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600)));
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000136}
137
138
139template<typename T>
140static int CompareProfileNodes(const T* p1, const T* p2) {
141 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name());
142}
143
144TEST(TickEvents) {
ager@chromium.org357bf652010-04-12 11:30:10 +0000145 TestSetup test_setup;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000146 CpuProfilesCollection profiles;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000147 profiles.StartProfiling("", 1);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000148 ProfileGenerator generator(&profiles);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000149 ProfilerEventsProcessor processor(i::Isolate::Current(), &generator);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000150 processor.Start();
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000151
152 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
153 "bbb",
154 ToAddress(0x1200),
155 0x80);
156 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
157 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
158 "ddd",
159 ToAddress(0x1400),
160 0x80);
161 EnqueueTickSampleEvent(&processor, ToAddress(0x1210));
162 EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220));
163 EnqueueTickSampleEvent(&processor,
164 ToAddress(0x1404),
165 ToAddress(0x1305),
166 ToAddress(0x1230));
167
168 processor.Stop();
169 processor.Join();
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000170 CpuProfile* profile =
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000171 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000172 CHECK_NE(NULL, profile);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000173
174 // Check call trees.
lrn@chromium.org25156de2010-04-06 13:10:27 +0000175 const i::List<ProfileNode*>* top_down_root_children =
176 profile->top_down()->root()->children();
177 CHECK_EQ(1, top_down_root_children->length());
178 CHECK_EQ("bbb", top_down_root_children->last()->entry()->name());
179 const i::List<ProfileNode*>* top_down_bbb_children =
180 top_down_root_children->last()->children();
181 CHECK_EQ(1, top_down_bbb_children->length());
182 CHECK_EQ("5", top_down_bbb_children->last()->entry()->name());
183 const i::List<ProfileNode*>* top_down_stub_children =
184 top_down_bbb_children->last()->children();
185 CHECK_EQ(1, top_down_stub_children->length());
186 CHECK_EQ("ddd", top_down_stub_children->last()->entry()->name());
187 const i::List<ProfileNode*>* top_down_ddd_children =
188 top_down_stub_children->last()->children();
189 CHECK_EQ(0, top_down_ddd_children->length());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000190
lrn@chromium.org25156de2010-04-06 13:10:27 +0000191 const i::List<ProfileNode*>* bottom_up_root_children_unsorted =
192 profile->bottom_up()->root()->children();
193 CHECK_EQ(3, bottom_up_root_children_unsorted->length());
194 i::List<ProfileNode*> bottom_up_root_children(3);
195 bottom_up_root_children.AddAll(*bottom_up_root_children_unsorted);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000196 bottom_up_root_children.Sort(&CompareProfileNodes);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000197 CHECK_EQ("5", bottom_up_root_children[0]->entry()->name());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000198 CHECK_EQ("bbb", bottom_up_root_children[1]->entry()->name());
199 CHECK_EQ("ddd", bottom_up_root_children[2]->entry()->name());
lrn@chromium.org25156de2010-04-06 13:10:27 +0000200 const i::List<ProfileNode*>* bottom_up_stub_children =
201 bottom_up_root_children[0]->children();
202 CHECK_EQ(1, bottom_up_stub_children->length());
203 CHECK_EQ("bbb", bottom_up_stub_children->last()->entry()->name());
204 const i::List<ProfileNode*>* bottom_up_bbb_children =
205 bottom_up_root_children[1]->children();
206 CHECK_EQ(0, bottom_up_bbb_children->length());
207 const i::List<ProfileNode*>* bottom_up_ddd_children =
208 bottom_up_root_children[2]->children();
209 CHECK_EQ(1, bottom_up_ddd_children->length());
210 CHECK_EQ("5", bottom_up_ddd_children->last()->entry()->name());
211 const i::List<ProfileNode*>* bottom_up_ddd_stub_children =
212 bottom_up_ddd_children->last()->children();
213 CHECK_EQ(1, bottom_up_ddd_stub_children->length());
214 CHECK_EQ("bbb", bottom_up_ddd_stub_children->last()->entry()->name());
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000215}
lrn@chromium.org25156de2010-04-06 13:10:27 +0000216
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000217
218// http://crbug/51594
219// This test must not crash.
220TEST(CrashIfStoppingLastNonExistentProfile) {
221 InitializeVM();
222 TestSetup test_setup;
223 CpuProfiler::Setup();
224 CpuProfiler::StartProfiling("1");
225 CpuProfiler::StopProfiling("2");
226 CpuProfiler::StartProfiling("1");
227 CpuProfiler::StopProfiling("");
228 CpuProfiler::TearDown();
229}
230
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000231
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000232// http://code.google.com/p/v8/issues/detail?id=1398
233// Long stacks (exceeding max frames limit) must not be erased.
234TEST(Issue1398) {
235 TestSetup test_setup;
236 CpuProfilesCollection profiles;
237 profiles.StartProfiling("", 1);
238 ProfileGenerator generator(&profiles);
239 ProfilerEventsProcessor processor(i::Isolate::Current(), &generator);
240 processor.Start();
241
242 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
243 "bbb",
244 ToAddress(0x1200),
245 0x80);
246
247 i::TickSample* sample = processor.TickSampleEvent();
248 sample->pc = ToAddress(0x1200);
249 sample->tos = 0;
250 sample->frames_count = i::TickSample::kMaxFramesCount;
251 for (int i = 0; i < sample->frames_count; ++i) {
252 sample->stack[i] = ToAddress(0x1200);
253 }
254
255 processor.Stop();
256 processor.Join();
257 CpuProfile* profile =
258 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
259 CHECK_NE(NULL, profile);
260
261 int actual_depth = 0;
262 const ProfileNode* node = profile->top_down()->root();
263 while (node->children()->length() > 0) {
264 node = node->children()->last();
265 ++actual_depth;
266 }
267
268 CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth); // +1 for PC.
269}
270
271
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000272TEST(DeleteAllCpuProfiles) {
273 InitializeVM();
274 TestSetup test_setup;
275 CpuProfiler::Setup();
276 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
277 CpuProfiler::DeleteAllProfiles();
278 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
279
280 CpuProfiler::StartProfiling("1");
281 CpuProfiler::StopProfiling("1");
282 CHECK_EQ(1, CpuProfiler::GetProfilesCount());
283 CpuProfiler::DeleteAllProfiles();
284 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
285 CpuProfiler::StartProfiling("1");
286 CpuProfiler::StartProfiling("2");
287 CpuProfiler::StopProfiling("2");
288 CpuProfiler::StopProfiling("1");
289 CHECK_EQ(2, CpuProfiler::GetProfilesCount());
290 CpuProfiler::DeleteAllProfiles();
291 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
292
293 // Test profiling cancellation by the 'delete' command.
294 CpuProfiler::StartProfiling("1");
295 CpuProfiler::StartProfiling("2");
296 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
297 CpuProfiler::DeleteAllProfiles();
298 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
299
300 CpuProfiler::TearDown();
301}
302
303
304TEST(DeleteCpuProfile) {
305 v8::HandleScope scope;
306 LocalContext env;
307
308 CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
309 v8::Local<v8::String> name1 = v8::String::New("1");
310 v8::CpuProfiler::StartProfiling(name1);
311 const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
312 CHECK_NE(NULL, p1);
313 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
314 unsigned uid1 = p1->GetUid();
315 CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
316 const_cast<v8::CpuProfile*>(p1)->Delete();
317 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
318 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
319
320 v8::Local<v8::String> name2 = v8::String::New("2");
321 v8::CpuProfiler::StartProfiling(name2);
322 const v8::CpuProfile* p2 = v8::CpuProfiler::StopProfiling(name2);
323 CHECK_NE(NULL, p2);
324 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
325 unsigned uid2 = p2->GetUid();
326 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
327 CHECK_EQ(p2, v8::CpuProfiler::FindProfile(uid2));
328 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
329 v8::Local<v8::String> name3 = v8::String::New("3");
330 v8::CpuProfiler::StartProfiling(name3);
331 const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
332 CHECK_NE(NULL, p3);
333 CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
334 unsigned uid3 = p3->GetUid();
335 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
336 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
337 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
338 const_cast<v8::CpuProfile*>(p2)->Delete();
339 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
340 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
341 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
342 const_cast<v8::CpuProfile*>(p3)->Delete();
343 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
344 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
345 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
346 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
347}
348
349
350TEST(DeleteCpuProfileDifferentTokens) {
351 v8::HandleScope scope;
352 LocalContext env;
353
354 CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
355 v8::Local<v8::String> name1 = v8::String::New("1");
356 v8::CpuProfiler::StartProfiling(name1);
357 const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
358 CHECK_NE(NULL, p1);
359 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
360 unsigned uid1 = p1->GetUid();
361 CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
362 v8::Local<v8::String> token1 = v8::String::New("token1");
363 const v8::CpuProfile* p1_t1 = v8::CpuProfiler::FindProfile(uid1, token1);
364 CHECK_NE(NULL, p1_t1);
365 CHECK_NE(p1, p1_t1);
366 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
367 const_cast<v8::CpuProfile*>(p1)->Delete();
368 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
369 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
370 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1, token1));
371 const_cast<v8::CpuProfile*>(p1_t1)->Delete();
372 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
373
374 v8::Local<v8::String> name2 = v8::String::New("2");
375 v8::CpuProfiler::StartProfiling(name2);
376 v8::Local<v8::String> token2 = v8::String::New("token2");
377 const v8::CpuProfile* p2_t2 = v8::CpuProfiler::StopProfiling(name2, token2);
378 CHECK_NE(NULL, p2_t2);
379 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
380 unsigned uid2 = p2_t2->GetUid();
381 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
382 const v8::CpuProfile* p2 = v8::CpuProfiler::FindProfile(uid2);
383 CHECK_NE(p2_t2, p2);
384 v8::Local<v8::String> name3 = v8::String::New("3");
385 v8::CpuProfiler::StartProfiling(name3);
386 const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
387 CHECK_NE(NULL, p3);
388 CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
389 unsigned uid3 = p3->GetUid();
390 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
391 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
392 const_cast<v8::CpuProfile*>(p2_t2)->Delete();
393 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
394 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
395 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
396 const_cast<v8::CpuProfile*>(p2)->Delete();
397 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
398 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
399 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
400 const_cast<v8::CpuProfile*>(p3)->Delete();
401 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
402 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
403}
404
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000405#endif // ENABLE_LOGGING_AND_PROFILING