blob: 749ac154340bda2e4ec91e86158e5cb212614d90 [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
2//
3// Tests of profiles generator and utilities.
4
5#ifdef ENABLE_LOGGING_AND_PROFILING
6
7#include "v8.h"
8#include "cpu-profiler-inl.h"
9#include "cctest.h"
Steve Block44f0eee2011-05-26 01:26:41 +010010#include "../include/v8-profiler.h"
Steve Block6ded16b2010-05-10 14:33:55 +010011
12namespace i = v8::internal;
13
14using i::CodeEntry;
15using i::CpuProfile;
Iain Merrick75681382010-08-19 15:07:18 +010016using i::CpuProfiler;
Steve Block6ded16b2010-05-10 14:33:55 +010017using i::CpuProfilesCollection;
18using i::ProfileGenerator;
19using i::ProfileNode;
20using i::ProfilerEventsProcessor;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010021using i::TokenEnumerator;
Steve Block6ded16b2010-05-10 14:33:55 +010022
23
24TEST(StartStop) {
25 CpuProfilesCollection profiles;
26 ProfileGenerator generator(&profiles);
Steve Block44f0eee2011-05-26 01:26:41 +010027 ProfilerEventsProcessor processor(i::Isolate::Current(), &generator);
Steve Block6ded16b2010-05-10 14:33:55 +010028 processor.Start();
29 while (!processor.running()) {
30 i::Thread::YieldCPU();
31 }
32 processor.Stop();
33 processor.Join();
34}
35
36static v8::Persistent<v8::Context> env;
37
38static void InitializeVM() {
39 if (env.IsEmpty()) env = v8::Context::New();
40 v8::HandleScope scope;
41 env->Enter();
42}
43
44static inline i::Address ToAddress(int n) {
45 return reinterpret_cast<i::Address>(n);
46}
47
48static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
49 i::Address frame1,
50 i::Address frame2 = NULL,
51 i::Address frame3 = NULL) {
52 i::TickSample* sample = proc->TickSampleEvent();
53 sample->pc = frame1;
Ben Murdoche0cee9b2011-05-25 10:26:03 +010054 sample->tos = frame1;
Steve Block6ded16b2010-05-10 14:33:55 +010055 sample->frames_count = 0;
56 if (frame2 != NULL) {
57 sample->stack[0] = frame2;
58 sample->frames_count = 1;
59 }
60 if (frame3 != NULL) {
61 sample->stack[1] = frame3;
62 sample->frames_count = 2;
63 }
64}
65
66namespace {
67
68class TestSetup {
69 public:
70 TestSetup()
71 : old_flag_prof_browser_mode_(i::FLAG_prof_browser_mode) {
72 i::FLAG_prof_browser_mode = false;
73 }
74
75 ~TestSetup() {
76 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_;
77 }
78
79 private:
80 bool old_flag_prof_browser_mode_;
81};
82
83} // namespace
84
85TEST(CodeEvents) {
86 InitializeVM();
87 TestSetup test_setup;
88 CpuProfilesCollection profiles;
89 profiles.StartProfiling("", 1);
90 ProfileGenerator generator(&profiles);
Steve Block44f0eee2011-05-26 01:26:41 +010091 ProfilerEventsProcessor processor(i::Isolate::Current(), &generator);
Steve Block6ded16b2010-05-10 14:33:55 +010092 processor.Start();
93 while (!processor.running()) {
94 i::Thread::YieldCPU();
95 }
96
97 // Enqueue code creation events.
98 i::HandleScope scope;
99 const char* aaa_str = "aaa";
Steve Block44f0eee2011-05-26 01:26:41 +0100100 i::Handle<i::String> aaa_name = FACTORY->NewStringFromAscii(
Steve Block6ded16b2010-05-10 14:33:55 +0100101 i::Vector<const char>(aaa_str, i::StrLength(aaa_str)));
102 processor.CodeCreateEvent(i::Logger::FUNCTION_TAG,
103 *aaa_name,
Steve Block44f0eee2011-05-26 01:26:41 +0100104 HEAP->empty_string(),
Steve Block6ded16b2010-05-10 14:33:55 +0100105 0,
106 ToAddress(0x1000),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100107 0x100,
108 ToAddress(0x10000));
Steve Block6ded16b2010-05-10 14:33:55 +0100109 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
110 "bbb",
111 ToAddress(0x1200),
112 0x80);
113 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
114 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
115 "ddd",
116 ToAddress(0x1400),
117 0x80);
118 processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500));
119 processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10);
120 processor.CodeDeleteEvent(ToAddress(0x1600));
Steve Block6ded16b2010-05-10 14:33:55 +0100121 // Enqueue a tick event to enable code events processing.
122 EnqueueTickSampleEvent(&processor, ToAddress(0x1000));
123
124 processor.Stop();
125 processor.Join();
126
127 // Check the state of profile generator.
128 CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000));
129 CHECK_NE(NULL, entry1);
130 CHECK_EQ(aaa_str, entry1->name());
131 CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200));
132 CHECK_NE(NULL, entry2);
133 CHECK_EQ("bbb", entry2->name());
134 CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300));
135 CHECK_NE(NULL, entry3);
136 CHECK_EQ("5", entry3->name());
137 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400)));
138 CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500));
139 CHECK_NE(NULL, entry4);
140 CHECK_EQ("ddd", entry4->name());
141 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600)));
Steve Block6ded16b2010-05-10 14:33:55 +0100142}
143
144
145template<typename T>
146static int CompareProfileNodes(const T* p1, const T* p2) {
147 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name());
148}
149
150TEST(TickEvents) {
151 TestSetup test_setup;
152 CpuProfilesCollection profiles;
153 profiles.StartProfiling("", 1);
154 ProfileGenerator generator(&profiles);
Steve Block44f0eee2011-05-26 01:26:41 +0100155 ProfilerEventsProcessor processor(i::Isolate::Current(), &generator);
Steve Block6ded16b2010-05-10 14:33:55 +0100156 processor.Start();
157 while (!processor.running()) {
158 i::Thread::YieldCPU();
159 }
160
161 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
162 "bbb",
163 ToAddress(0x1200),
164 0x80);
165 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
166 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
167 "ddd",
168 ToAddress(0x1400),
169 0x80);
170 EnqueueTickSampleEvent(&processor, ToAddress(0x1210));
171 EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220));
172 EnqueueTickSampleEvent(&processor,
173 ToAddress(0x1404),
174 ToAddress(0x1305),
175 ToAddress(0x1230));
176
177 processor.Stop();
178 processor.Join();
Leon Clarkef7060e22010-06-03 12:02:55 +0100179 CpuProfile* profile =
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100180 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
Steve Block6ded16b2010-05-10 14:33:55 +0100181 CHECK_NE(NULL, profile);
182
183 // Check call trees.
184 const i::List<ProfileNode*>* top_down_root_children =
185 profile->top_down()->root()->children();
186 CHECK_EQ(1, top_down_root_children->length());
187 CHECK_EQ("bbb", top_down_root_children->last()->entry()->name());
188 const i::List<ProfileNode*>* top_down_bbb_children =
189 top_down_root_children->last()->children();
190 CHECK_EQ(1, top_down_bbb_children->length());
191 CHECK_EQ("5", top_down_bbb_children->last()->entry()->name());
192 const i::List<ProfileNode*>* top_down_stub_children =
193 top_down_bbb_children->last()->children();
194 CHECK_EQ(1, top_down_stub_children->length());
195 CHECK_EQ("ddd", top_down_stub_children->last()->entry()->name());
196 const i::List<ProfileNode*>* top_down_ddd_children =
197 top_down_stub_children->last()->children();
198 CHECK_EQ(0, top_down_ddd_children->length());
199
200 const i::List<ProfileNode*>* bottom_up_root_children_unsorted =
201 profile->bottom_up()->root()->children();
202 CHECK_EQ(3, bottom_up_root_children_unsorted->length());
203 i::List<ProfileNode*> bottom_up_root_children(3);
204 bottom_up_root_children.AddAll(*bottom_up_root_children_unsorted);
205 bottom_up_root_children.Sort(&CompareProfileNodes);
206 CHECK_EQ("5", bottom_up_root_children[0]->entry()->name());
207 CHECK_EQ("bbb", bottom_up_root_children[1]->entry()->name());
208 CHECK_EQ("ddd", bottom_up_root_children[2]->entry()->name());
209 const i::List<ProfileNode*>* bottom_up_stub_children =
210 bottom_up_root_children[0]->children();
211 CHECK_EQ(1, bottom_up_stub_children->length());
212 CHECK_EQ("bbb", bottom_up_stub_children->last()->entry()->name());
213 const i::List<ProfileNode*>* bottom_up_bbb_children =
214 bottom_up_root_children[1]->children();
215 CHECK_EQ(0, bottom_up_bbb_children->length());
216 const i::List<ProfileNode*>* bottom_up_ddd_children =
217 bottom_up_root_children[2]->children();
218 CHECK_EQ(1, bottom_up_ddd_children->length());
219 CHECK_EQ("5", bottom_up_ddd_children->last()->entry()->name());
220 const i::List<ProfileNode*>* bottom_up_ddd_stub_children =
221 bottom_up_ddd_children->last()->children();
222 CHECK_EQ(1, bottom_up_ddd_stub_children->length());
223 CHECK_EQ("bbb", bottom_up_ddd_stub_children->last()->entry()->name());
224}
225
Iain Merrick75681382010-08-19 15:07:18 +0100226
227// http://crbug/51594
228// This test must not crash.
229TEST(CrashIfStoppingLastNonExistentProfile) {
230 InitializeVM();
231 TestSetup test_setup;
232 CpuProfiler::Setup();
233 CpuProfiler::StartProfiling("1");
234 CpuProfiler::StopProfiling("2");
235 CpuProfiler::StartProfiling("1");
236 CpuProfiler::StopProfiling("");
237 CpuProfiler::TearDown();
238}
239
Steve Block44f0eee2011-05-26 01:26:41 +0100240
241TEST(DeleteAllCpuProfiles) {
242 InitializeVM();
243 TestSetup test_setup;
244 CpuProfiler::Setup();
245 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
246 CpuProfiler::DeleteAllProfiles();
247 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
248
249 CpuProfiler::StartProfiling("1");
250 CpuProfiler::StopProfiling("1");
251 CHECK_EQ(1, CpuProfiler::GetProfilesCount());
252 CpuProfiler::DeleteAllProfiles();
253 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
254 CpuProfiler::StartProfiling("1");
255 CpuProfiler::StartProfiling("2");
256 CpuProfiler::StopProfiling("2");
257 CpuProfiler::StopProfiling("1");
258 CHECK_EQ(2, CpuProfiler::GetProfilesCount());
259 CpuProfiler::DeleteAllProfiles();
260 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
261
262 // Test profiling cancellation by the 'delete' command.
263 CpuProfiler::StartProfiling("1");
264 CpuProfiler::StartProfiling("2");
265 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
266 CpuProfiler::DeleteAllProfiles();
267 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
268
269 CpuProfiler::TearDown();
270}
271
272
273TEST(DeleteCpuProfile) {
274 v8::HandleScope scope;
275 LocalContext env;
276
277 CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
278 v8::Local<v8::String> name1 = v8::String::New("1");
279 v8::CpuProfiler::StartProfiling(name1);
280 const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
281 CHECK_NE(NULL, p1);
282 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
283 unsigned uid1 = p1->GetUid();
284 CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
285 const_cast<v8::CpuProfile*>(p1)->Delete();
286 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
287 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
288
289 v8::Local<v8::String> name2 = v8::String::New("2");
290 v8::CpuProfiler::StartProfiling(name2);
291 const v8::CpuProfile* p2 = v8::CpuProfiler::StopProfiling(name2);
292 CHECK_NE(NULL, p2);
293 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
294 unsigned uid2 = p2->GetUid();
295 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
296 CHECK_EQ(p2, v8::CpuProfiler::FindProfile(uid2));
297 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
298 v8::Local<v8::String> name3 = v8::String::New("3");
299 v8::CpuProfiler::StartProfiling(name3);
300 const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
301 CHECK_NE(NULL, p3);
302 CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
303 unsigned uid3 = p3->GetUid();
304 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
305 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
306 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
307 const_cast<v8::CpuProfile*>(p2)->Delete();
308 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
309 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
310 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
311 const_cast<v8::CpuProfile*>(p3)->Delete();
312 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
313 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
314 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
315 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
316}
317
318
319TEST(DeleteCpuProfileDifferentTokens) {
320 v8::HandleScope scope;
321 LocalContext env;
322
323 CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
324 v8::Local<v8::String> name1 = v8::String::New("1");
325 v8::CpuProfiler::StartProfiling(name1);
326 const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
327 CHECK_NE(NULL, p1);
328 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
329 unsigned uid1 = p1->GetUid();
330 CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
331 v8::Local<v8::String> token1 = v8::String::New("token1");
332 const v8::CpuProfile* p1_t1 = v8::CpuProfiler::FindProfile(uid1, token1);
333 CHECK_NE(NULL, p1_t1);
334 CHECK_NE(p1, p1_t1);
335 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
336 const_cast<v8::CpuProfile*>(p1)->Delete();
337 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
338 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
339 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1, token1));
340 const_cast<v8::CpuProfile*>(p1_t1)->Delete();
341 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
342
343 v8::Local<v8::String> name2 = v8::String::New("2");
344 v8::CpuProfiler::StartProfiling(name2);
345 v8::Local<v8::String> token2 = v8::String::New("token2");
346 const v8::CpuProfile* p2_t2 = v8::CpuProfiler::StopProfiling(name2, token2);
347 CHECK_NE(NULL, p2_t2);
348 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
349 unsigned uid2 = p2_t2->GetUid();
350 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
351 const v8::CpuProfile* p2 = v8::CpuProfiler::FindProfile(uid2);
352 CHECK_NE(p2_t2, p2);
353 v8::Local<v8::String> name3 = v8::String::New("3");
354 v8::CpuProfiler::StartProfiling(name3);
355 const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
356 CHECK_NE(NULL, p3);
357 CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
358 unsigned uid3 = p3->GetUid();
359 CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
360 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
361 const_cast<v8::CpuProfile*>(p2_t2)->Delete();
362 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
363 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
364 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
365 const_cast<v8::CpuProfile*>(p2)->Delete();
366 CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
367 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
368 CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
369 const_cast<v8::CpuProfile*>(p3)->Delete();
370 CHECK_EQ(0, CpuProfiler::GetProfilesCount());
371 CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
372}
373
Steve Block6ded16b2010-05-10 14:33:55 +0100374#endif // ENABLE_LOGGING_AND_PROFILING