blob: 0e6f09d2ef0159c6aff2b0d8cebf0fc5e8c79fb8 [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"
10
11namespace i = v8::internal;
12
13using i::CodeEntry;
14using i::CpuProfile;
15using i::CpuProfilesCollection;
16using i::ProfileGenerator;
17using i::ProfileNode;
18using i::ProfilerEventsProcessor;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010019using i::TokenEnumerator;
Steve Block6ded16b2010-05-10 14:33:55 +010020
21
22TEST(StartStop) {
23 CpuProfilesCollection profiles;
24 ProfileGenerator generator(&profiles);
25 ProfilerEventsProcessor processor(&generator);
26 processor.Start();
27 while (!processor.running()) {
28 i::Thread::YieldCPU();
29 }
30 processor.Stop();
31 processor.Join();
32}
33
34static v8::Persistent<v8::Context> env;
35
36static void InitializeVM() {
37 if (env.IsEmpty()) env = v8::Context::New();
38 v8::HandleScope scope;
39 env->Enter();
40}
41
42static inline i::Address ToAddress(int n) {
43 return reinterpret_cast<i::Address>(n);
44}
45
46static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
47 i::Address frame1,
48 i::Address frame2 = NULL,
49 i::Address frame3 = NULL) {
50 i::TickSample* sample = proc->TickSampleEvent();
51 sample->pc = frame1;
52 sample->function = frame1;
53 sample->frames_count = 0;
54 if (frame2 != NULL) {
55 sample->stack[0] = frame2;
56 sample->frames_count = 1;
57 }
58 if (frame3 != NULL) {
59 sample->stack[1] = frame3;
60 sample->frames_count = 2;
61 }
62}
63
64namespace {
65
66class TestSetup {
67 public:
68 TestSetup()
69 : old_flag_prof_browser_mode_(i::FLAG_prof_browser_mode) {
70 i::FLAG_prof_browser_mode = false;
71 }
72
73 ~TestSetup() {
74 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_;
75 }
76
77 private:
78 bool old_flag_prof_browser_mode_;
79};
80
81} // namespace
82
83TEST(CodeEvents) {
84 InitializeVM();
85 TestSetup test_setup;
86 CpuProfilesCollection profiles;
87 profiles.StartProfiling("", 1);
88 ProfileGenerator generator(&profiles);
89 ProfilerEventsProcessor processor(&generator);
90 processor.Start();
91 while (!processor.running()) {
92 i::Thread::YieldCPU();
93 }
94
95 // Enqueue code creation events.
96 i::HandleScope scope;
97 const char* aaa_str = "aaa";
98 i::Handle<i::String> aaa_name = i::Factory::NewStringFromAscii(
99 i::Vector<const char>(aaa_str, i::StrLength(aaa_str)));
100 processor.CodeCreateEvent(i::Logger::FUNCTION_TAG,
101 *aaa_name,
102 i::Heap::empty_string(),
103 0,
104 ToAddress(0x1000),
105 0x100);
106 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
107 "bbb",
108 ToAddress(0x1200),
109 0x80);
110 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
111 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
112 "ddd",
113 ToAddress(0x1400),
114 0x80);
115 processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500));
116 processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10);
117 processor.CodeDeleteEvent(ToAddress(0x1600));
Leon Clarkef7060e22010-06-03 12:02:55 +0100118 processor.FunctionCreateEvent(ToAddress(0x1700), ToAddress(0x1000),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100119 TokenEnumerator::kNoSecurityToken);
Steve Block6ded16b2010-05-10 14:33:55 +0100120 // Enqueue a tick event to enable code events processing.
121 EnqueueTickSampleEvent(&processor, ToAddress(0x1000));
122
123 processor.Stop();
124 processor.Join();
125
126 // Check the state of profile generator.
127 CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000));
128 CHECK_NE(NULL, entry1);
129 CHECK_EQ(aaa_str, entry1->name());
130 CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200));
131 CHECK_NE(NULL, entry2);
132 CHECK_EQ("bbb", entry2->name());
133 CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300));
134 CHECK_NE(NULL, entry3);
135 CHECK_EQ("5", entry3->name());
136 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400)));
137 CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500));
138 CHECK_NE(NULL, entry4);
139 CHECK_EQ("ddd", entry4->name());
140 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600)));
141 CodeEntry* entry5 = generator.code_map()->FindEntry(ToAddress(0x1700));
142 CHECK_NE(NULL, entry5);
143 CHECK_EQ(aaa_str, entry5->name());
144}
145
146
147template<typename T>
148static int CompareProfileNodes(const T* p1, const T* p2) {
149 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name());
150}
151
152TEST(TickEvents) {
153 TestSetup test_setup;
154 CpuProfilesCollection profiles;
155 profiles.StartProfiling("", 1);
156 ProfileGenerator generator(&profiles);
157 ProfilerEventsProcessor processor(&generator);
158 processor.Start();
159 while (!processor.running()) {
160 i::Thread::YieldCPU();
161 }
162
163 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
164 "bbb",
165 ToAddress(0x1200),
166 0x80);
167 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
168 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
169 "ddd",
170 ToAddress(0x1400),
171 0x80);
172 EnqueueTickSampleEvent(&processor, ToAddress(0x1210));
173 EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220));
174 EnqueueTickSampleEvent(&processor,
175 ToAddress(0x1404),
176 ToAddress(0x1305),
177 ToAddress(0x1230));
178
179 processor.Stop();
180 processor.Join();
Leon Clarkef7060e22010-06-03 12:02:55 +0100181 CpuProfile* profile =
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100182 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
Steve Block6ded16b2010-05-10 14:33:55 +0100183 CHECK_NE(NULL, profile);
184
185 // Check call trees.
186 const i::List<ProfileNode*>* top_down_root_children =
187 profile->top_down()->root()->children();
188 CHECK_EQ(1, top_down_root_children->length());
189 CHECK_EQ("bbb", top_down_root_children->last()->entry()->name());
190 const i::List<ProfileNode*>* top_down_bbb_children =
191 top_down_root_children->last()->children();
192 CHECK_EQ(1, top_down_bbb_children->length());
193 CHECK_EQ("5", top_down_bbb_children->last()->entry()->name());
194 const i::List<ProfileNode*>* top_down_stub_children =
195 top_down_bbb_children->last()->children();
196 CHECK_EQ(1, top_down_stub_children->length());
197 CHECK_EQ("ddd", top_down_stub_children->last()->entry()->name());
198 const i::List<ProfileNode*>* top_down_ddd_children =
199 top_down_stub_children->last()->children();
200 CHECK_EQ(0, top_down_ddd_children->length());
201
202 const i::List<ProfileNode*>* bottom_up_root_children_unsorted =
203 profile->bottom_up()->root()->children();
204 CHECK_EQ(3, bottom_up_root_children_unsorted->length());
205 i::List<ProfileNode*> bottom_up_root_children(3);
206 bottom_up_root_children.AddAll(*bottom_up_root_children_unsorted);
207 bottom_up_root_children.Sort(&CompareProfileNodes);
208 CHECK_EQ("5", bottom_up_root_children[0]->entry()->name());
209 CHECK_EQ("bbb", bottom_up_root_children[1]->entry()->name());
210 CHECK_EQ("ddd", bottom_up_root_children[2]->entry()->name());
211 const i::List<ProfileNode*>* bottom_up_stub_children =
212 bottom_up_root_children[0]->children();
213 CHECK_EQ(1, bottom_up_stub_children->length());
214 CHECK_EQ("bbb", bottom_up_stub_children->last()->entry()->name());
215 const i::List<ProfileNode*>* bottom_up_bbb_children =
216 bottom_up_root_children[1]->children();
217 CHECK_EQ(0, bottom_up_bbb_children->length());
218 const i::List<ProfileNode*>* bottom_up_ddd_children =
219 bottom_up_root_children[2]->children();
220 CHECK_EQ(1, bottom_up_ddd_children->length());
221 CHECK_EQ("5", bottom_up_ddd_children->last()->entry()->name());
222 const i::List<ProfileNode*>* bottom_up_ddd_stub_children =
223 bottom_up_ddd_children->last()->children();
224 CHECK_EQ(1, bottom_up_ddd_stub_children->length());
225 CHECK_EQ("bbb", bottom_up_ddd_stub_children->last()->entry()->name());
226}
227
228#endif // ENABLE_LOGGING_AND_PROFILING