OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 13 matching lines...) Expand all Loading... |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 // | 27 // |
28 // Tests of profiles generator and utilities. | 28 // Tests of profiles generator and utilities. |
29 | 29 |
30 #define V8_DISABLE_DEPRECATIONS 1 | 30 #define V8_DISABLE_DEPRECATIONS 1 |
31 #include "v8.h" | 31 #include "v8.h" |
32 #include "cpu-profiler-inl.h" | 32 #include "cpu-profiler-inl.h" |
33 #include "cctest.h" | 33 #include "cctest.h" |
| 34 #include "platform.h" |
34 #include "utils.h" | 35 #include "utils.h" |
35 #include "../include/v8-profiler.h" | 36 #include "../include/v8-profiler.h" |
36 #undef V8_DISABLE_DEPRECATIONS | 37 #undef V8_DISABLE_DEPRECATIONS |
37 | 38 |
38 using i::CodeEntry; | 39 using i::CodeEntry; |
39 using i::CpuProfile; | 40 using i::CpuProfile; |
40 using i::CpuProfiler; | 41 using i::CpuProfiler; |
41 using i::CpuProfilesCollection; | 42 using i::CpuProfilesCollection; |
42 using i::ProfileGenerator; | 43 using i::ProfileGenerator; |
43 using i::ProfileNode; | 44 using i::ProfileNode; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 ~TestSetup() { | 91 ~TestSetup() { |
91 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_; | 92 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_; |
92 } | 93 } |
93 | 94 |
94 private: | 95 private: |
95 bool old_flag_prof_browser_mode_; | 96 bool old_flag_prof_browser_mode_; |
96 }; | 97 }; |
97 | 98 |
98 } // namespace | 99 } // namespace |
99 | 100 |
| 101 |
| 102 i::Code* CreateCode(LocalContext* env) { |
| 103 static int counter = 0; |
| 104 i::EmbeddedVector<char, 256> script; |
| 105 i::EmbeddedVector<char, 32> name; |
| 106 |
| 107 i::OS::SNPrintF(name, "function_%d", ++counter); |
| 108 const char* name_start = name.start(); |
| 109 i::OS::SNPrintF(script, |
| 110 "function %s() {\n" |
| 111 "var counter = 0;\n" |
| 112 "for (var i = 0; i < %d; ++i) counter += i;\n" |
| 113 "return '%s_' + counter;\n" |
| 114 "}\n" |
| 115 "%s();\n", name_start, counter, name_start, name_start); |
| 116 CompileRun(script.start()); |
| 117 i::Handle<i::JSFunction> fun = v8::Utils::OpenHandle( |
| 118 *v8::Local<v8::Function>::Cast( |
| 119 (*env)->Global()->Get(v8_str(name_start)))); |
| 120 return fun->code(); |
| 121 } |
| 122 |
| 123 |
100 TEST(CodeEvents) { | 124 TEST(CodeEvents) { |
101 CcTest::InitializeVM(); | 125 CcTest::InitializeVM(); |
| 126 LocalContext env; |
102 i::Isolate* isolate = i::Isolate::Current(); | 127 i::Isolate* isolate = i::Isolate::Current(); |
103 i::Heap* heap = isolate->heap(); | |
104 i::Factory* factory = isolate->factory(); | 128 i::Factory* factory = isolate->factory(); |
105 TestSetup test_setup; | 129 TestSetup test_setup; |
106 CpuProfilesCollection profiles; | 130 |
107 profiles.StartProfiling("", 1, false); | 131 i::HandleScope scope(isolate); |
108 ProfileGenerator generator(&profiles); | 132 |
109 ProfilerEventsProcessor processor(&generator, &profiles); | 133 i::Code* aaa_code = CreateCode(&env); |
| 134 i::Code* comment_code = CreateCode(&env); |
| 135 i::Code* args5_code = CreateCode(&env); |
| 136 i::Code* comment2_code = CreateCode(&env); |
| 137 i::Code* moved_code = CreateCode(&env); |
| 138 i::Code* args3_code = CreateCode(&env); |
| 139 i::Code* args4_code = CreateCode(&env); |
| 140 |
| 141 CpuProfilesCollection* profiles = new CpuProfilesCollection; |
| 142 profiles->StartProfiling("", 1, false); |
| 143 ProfileGenerator generator(profiles); |
| 144 ProfilerEventsProcessor processor(&generator, profiles); |
110 processor.Start(); | 145 processor.Start(); |
| 146 CpuProfiler profiler(isolate, profiles, &generator, &processor); |
111 | 147 |
112 // Enqueue code creation events. | 148 // Enqueue code creation events. |
113 i::HandleScope scope(isolate); | |
114 const char* aaa_str = "aaa"; | 149 const char* aaa_str = "aaa"; |
115 i::Handle<i::String> aaa_name = factory->NewStringFromAscii( | 150 i::Handle<i::String> aaa_name = factory->NewStringFromAscii( |
116 i::Vector<const char>(aaa_str, i::StrLength(aaa_str))); | 151 i::Vector<const char>(aaa_str, i::StrLength(aaa_str))); |
117 processor.CodeCreateEvent(i::Logger::FUNCTION_TAG, | 152 profiler.CodeCreateEvent(i::Logger::FUNCTION_TAG, aaa_code, *aaa_name); |
118 *aaa_name, | 153 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment_code, "comment"); |
119 heap->empty_string(), | 154 profiler.CodeCreateEvent(i::Logger::STUB_TAG, args5_code, 5); |
120 0, | 155 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment2_code, "comment2"); |
121 ToAddress(0x1000), | 156 profiler.CodeMoveEvent(comment2_code->address(), moved_code->address()); |
122 0x100, | 157 profiler.CodeCreateEvent(i::Logger::STUB_TAG, args3_code, 3); |
123 ToAddress(0x10000), | 158 profiler.CodeCreateEvent(i::Logger::STUB_TAG, args4_code, 4); |
124 NULL); | 159 |
125 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, | |
126 "bbb", | |
127 ToAddress(0x1200), | |
128 0x80); | |
129 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10); | |
130 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, | |
131 "ddd", | |
132 ToAddress(0x1400), | |
133 0x80); | |
134 processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500)); | |
135 processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10); | |
136 processor.CodeCreateEvent(i::Logger::STUB_TAG, 4, ToAddress(0x1605), 0x10); | |
137 // Enqueue a tick event to enable code events processing. | 160 // Enqueue a tick event to enable code events processing. |
138 EnqueueTickSampleEvent(&processor, ToAddress(0x1000)); | 161 EnqueueTickSampleEvent(&processor, aaa_code->address()); |
139 | 162 |
140 processor.Stop(); | 163 processor.Stop(); |
141 processor.Join(); | 164 processor.Join(); |
142 | 165 |
143 // Check the state of profile generator. | 166 // Check the state of profile generator. |
144 CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000)); | 167 CodeEntry* aaa = generator.code_map()->FindEntry(aaa_code->address()); |
145 CHECK_NE(NULL, entry1); | 168 CHECK_NE(NULL, aaa); |
146 CHECK_EQ(aaa_str, entry1->name()); | 169 CHECK_EQ(aaa_str, aaa->name()); |
147 CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200)); | 170 |
148 CHECK_NE(NULL, entry2); | 171 CodeEntry* comment = generator.code_map()->FindEntry(comment_code->address()); |
149 CHECK_EQ("bbb", entry2->name()); | 172 CHECK_NE(NULL, comment); |
150 CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300)); | 173 CHECK_EQ("comment", comment->name()); |
151 CHECK_NE(NULL, entry3); | 174 |
152 CHECK_EQ("5", entry3->name()); | 175 CodeEntry* args5 = generator.code_map()->FindEntry(args5_code->address()); |
153 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400))); | 176 CHECK_NE(NULL, args5); |
154 CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500)); | 177 CHECK_EQ("5", args5->name()); |
155 CHECK_NE(NULL, entry4); | 178 |
156 CHECK_EQ("ddd", entry4->name()); | 179 CHECK_EQ(NULL, generator.code_map()->FindEntry(comment2_code->address())); |
157 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600))); | 180 |
| 181 CodeEntry* comment2 = generator.code_map()->FindEntry(moved_code->address()); |
| 182 CHECK_NE(NULL, comment2); |
| 183 CHECK_EQ("comment2", comment2->name()); |
158 } | 184 } |
159 | 185 |
160 | 186 |
161 template<typename T> | 187 template<typename T> |
162 static int CompareProfileNodes(const T* p1, const T* p2) { | 188 static int CompareProfileNodes(const T* p1, const T* p2) { |
163 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name()); | 189 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name()); |
164 } | 190 } |
165 | 191 |
166 TEST(TickEvents) { | 192 TEST(TickEvents) { |
167 TestSetup test_setup; | 193 TestSetup test_setup; |
168 CpuProfilesCollection profiles; | 194 LocalContext env; |
169 profiles.StartProfiling("", 1, false); | 195 i::Isolate* isolate = i::Isolate::Current(); |
170 ProfileGenerator generator(&profiles); | 196 i::HandleScope scope(isolate); |
171 ProfilerEventsProcessor processor(&generator, &profiles); | 197 |
| 198 i::Code* frame1_code = CreateCode(&env); |
| 199 i::Code* frame2_code = CreateCode(&env); |
| 200 i::Code* frame3_code = CreateCode(&env); |
| 201 |
| 202 CpuProfilesCollection* profiles = new CpuProfilesCollection; |
| 203 profiles->StartProfiling("", 1, false); |
| 204 ProfileGenerator generator(profiles); |
| 205 ProfilerEventsProcessor processor(&generator, profiles); |
172 processor.Start(); | 206 processor.Start(); |
| 207 CpuProfiler profiler(isolate, profiles, &generator, &processor); |
173 | 208 |
174 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, | 209 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame1_code, "bbb"); |
175 "bbb", | 210 profiler.CodeCreateEvent(i::Logger::STUB_TAG, frame2_code, 5); |
176 ToAddress(0x1200), | 211 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame3_code, "ddd"); |
177 0x80); | 212 |
178 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10); | 213 EnqueueTickSampleEvent(&processor, frame1_code->instruction_start()); |
179 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, | 214 EnqueueTickSampleEvent( |
180 "ddd", | 215 &processor, |
181 ToAddress(0x1400), | 216 frame2_code->instruction_start() + frame2_code->ExecutableSize() / 2, |
182 0x80); | 217 frame1_code->instruction_start() + frame2_code->ExecutableSize() / 2); |
183 EnqueueTickSampleEvent(&processor, ToAddress(0x1210)); | 218 EnqueueTickSampleEvent( |
184 EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220)); | 219 &processor, |
185 EnqueueTickSampleEvent(&processor, | 220 frame3_code->instruction_end() - 1, |
186 ToAddress(0x1404), | 221 frame2_code->instruction_end() - 1, |
187 ToAddress(0x1305), | 222 frame1_code->instruction_end() - 1); |
188 ToAddress(0x1230)); | |
189 | 223 |
190 processor.Stop(); | 224 processor.Stop(); |
191 processor.Join(); | 225 processor.Join(); |
192 CpuProfile* profile = | 226 CpuProfile* profile = |
193 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); | 227 profiles->StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); |
194 CHECK_NE(NULL, profile); | 228 CHECK_NE(NULL, profile); |
195 | 229 |
196 // Check call trees. | 230 // Check call trees. |
197 const i::List<ProfileNode*>* top_down_root_children = | 231 const i::List<ProfileNode*>* top_down_root_children = |
198 profile->top_down()->root()->children(); | 232 profile->top_down()->root()->children(); |
199 CHECK_EQ(1, top_down_root_children->length()); | 233 CHECK_EQ(1, top_down_root_children->length()); |
200 CHECK_EQ("bbb", top_down_root_children->last()->entry()->name()); | 234 CHECK_EQ("bbb", top_down_root_children->last()->entry()->name()); |
201 const i::List<ProfileNode*>* top_down_bbb_children = | 235 const i::List<ProfileNode*>* top_down_bbb_children = |
202 top_down_root_children->last()->children(); | 236 top_down_root_children->last()->children(); |
203 CHECK_EQ(1, top_down_bbb_children->length()); | 237 CHECK_EQ(1, top_down_bbb_children->length()); |
(...skipping 18 matching lines...) Expand all Loading... |
222 profiler->StopProfiling("2"); | 256 profiler->StopProfiling("2"); |
223 profiler->StartProfiling("1"); | 257 profiler->StartProfiling("1"); |
224 profiler->StopProfiling(""); | 258 profiler->StopProfiling(""); |
225 } | 259 } |
226 | 260 |
227 | 261 |
228 // http://code.google.com/p/v8/issues/detail?id=1398 | 262 // http://code.google.com/p/v8/issues/detail?id=1398 |
229 // Long stacks (exceeding max frames limit) must not be erased. | 263 // Long stacks (exceeding max frames limit) must not be erased. |
230 TEST(Issue1398) { | 264 TEST(Issue1398) { |
231 TestSetup test_setup; | 265 TestSetup test_setup; |
232 CpuProfilesCollection profiles; | 266 LocalContext env; |
233 profiles.StartProfiling("", 1, false); | 267 i::Isolate* isolate = i::Isolate::Current(); |
234 ProfileGenerator generator(&profiles); | 268 i::HandleScope scope(isolate); |
235 ProfilerEventsProcessor processor(&generator, &profiles); | 269 |
| 270 i::Code* code = CreateCode(&env); |
| 271 |
| 272 CpuProfilesCollection* profiles = new CpuProfilesCollection; |
| 273 profiles->StartProfiling("", 1, false); |
| 274 ProfileGenerator generator(profiles); |
| 275 ProfilerEventsProcessor processor(&generator, profiles); |
236 processor.Start(); | 276 processor.Start(); |
| 277 CpuProfiler profiler(isolate, profiles, &generator, &processor); |
237 | 278 |
238 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, | 279 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb"); |
239 "bbb", | |
240 ToAddress(0x1200), | |
241 0x80); | |
242 | 280 |
243 i::TickSample* sample = processor.TickSampleEvent(); | 281 i::TickSample* sample = processor.TickSampleEvent(); |
244 sample->pc = ToAddress(0x1200); | 282 sample->pc = code->address(); |
245 sample->tos = 0; | 283 sample->tos = 0; |
246 sample->frames_count = i::TickSample::kMaxFramesCount; | 284 sample->frames_count = i::TickSample::kMaxFramesCount; |
247 for (int i = 0; i < sample->frames_count; ++i) { | 285 for (int i = 0; i < sample->frames_count; ++i) { |
248 sample->stack[i] = ToAddress(0x1200); | 286 sample->stack[i] = code->address(); |
249 } | 287 } |
250 | 288 |
251 processor.Stop(); | 289 processor.Stop(); |
252 processor.Join(); | 290 processor.Join(); |
253 CpuProfile* profile = | 291 CpuProfile* profile = |
254 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); | 292 profiles->StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); |
255 CHECK_NE(NULL, profile); | 293 CHECK_NE(NULL, profile); |
256 | 294 |
257 int actual_depth = 0; | 295 int actual_depth = 0; |
258 const ProfileNode* node = profile->top_down()->root(); | 296 const ProfileNode* node = profile->top_down()->root(); |
259 while (node->children()->length() > 0) { | 297 while (node->children()->length() > 0) { |
260 node = node->children()->last(); | 298 node = node->children()->last(); |
261 ++actual_depth; | 299 ++actual_depth; |
262 } | 300 } |
263 | 301 |
264 CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth); // +1 for PC. | 302 CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth); // +1 for PC. |
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); | 996 names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); |
959 names[2] = v8::String::New("start"); | 997 names[2] = v8::String::New("start"); |
960 // Don't allow |foo| node to be at the top level. | 998 // Don't allow |foo| node to be at the top level. |
961 CheckChildrenNames(root, names); | 999 CheckChildrenNames(root, names); |
962 | 1000 |
963 const v8::CpuProfileNode* startNode = GetChild(root, "start"); | 1001 const v8::CpuProfileNode* startNode = GetChild(root, "start"); |
964 GetChild(startNode, "foo"); | 1002 GetChild(startNode, "foo"); |
965 | 1003 |
966 cpu_profiler->DeleteAllCpuProfiles(); | 1004 cpu_profiler->DeleteAllCpuProfiles(); |
967 } | 1005 } |
OLD | NEW |