| 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 ~TestSetup() { | 90 ~TestSetup() { |
| 91 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_; | 91 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_; |
| 92 } | 92 } |
| 93 | 93 |
| 94 private: | 94 private: |
| 95 bool old_flag_prof_browser_mode_; | 95 bool old_flag_prof_browser_mode_; |
| 96 }; | 96 }; |
| 97 | 97 |
| 98 } // namespace | 98 } // namespace |
| 99 | 99 |
| 100 | |
| 101 i::Code* CreateCode(LocalContext* env) { | |
| 102 static int counter = 0; | |
| 103 char script[256]; | |
| 104 char name[32]; | |
| 105 snprintf(name, sizeof(name), "function_%d", ++counter); | |
| 106 snprintf(script, sizeof(script), | |
| 107 "function %s() {\n" | |
| 108 "var counter = 0;\n" | |
| 109 "for (var i = 0; i < %d; ++i) counter += i;\n" | |
| 110 "return '%s_' + counter;\n" | |
| 111 "}\n" | |
| 112 "%s();\n", name, counter, name, name); | |
| 113 CompileRun(script); | |
| 114 i::Handle<i::JSFunction> fun = v8::Utils::OpenHandle( | |
| 115 *v8::Local<v8::Function>::Cast((*env)->Global()->Get(v8_str(name)))); | |
| 116 fprintf(stderr, "code size: %d\n", fun->code()->ExecutableSize()); | |
| 117 return fun->code(); | |
| 118 } | |
| 119 | |
| 120 | |
| 121 TEST(CodeEvents) { | 100 TEST(CodeEvents) { |
| 122 CcTest::InitializeVM(); | 101 CcTest::InitializeVM(); |
| 123 LocalContext env; | |
| 124 i::Isolate* isolate = i::Isolate::Current(); | 102 i::Isolate* isolate = i::Isolate::Current(); |
| 103 i::Heap* heap = isolate->heap(); |
| 125 i::Factory* factory = isolate->factory(); | 104 i::Factory* factory = isolate->factory(); |
| 126 TestSetup test_setup; | 105 TestSetup test_setup; |
| 127 | 106 CpuProfilesCollection profiles; |
| 128 i::HandleScope scope(isolate); | 107 profiles.StartProfiling("", 1, false); |
| 129 | 108 ProfileGenerator generator(&profiles); |
| 130 i::Code* aaa_code = CreateCode(&env); | 109 ProfilerEventsProcessor processor(&generator, &profiles); |
| 131 i::Code* comment_code = CreateCode(&env); | |
| 132 i::Code* args5_code = CreateCode(&env); | |
| 133 i::Code* comment2_code = CreateCode(&env); | |
| 134 i::Code* moved_code = CreateCode(&env); | |
| 135 i::Code* args3_code = CreateCode(&env); | |
| 136 i::Code* args4_code = CreateCode(&env); | |
| 137 | |
| 138 CpuProfilesCollection* profiles = new CpuProfilesCollection; | |
| 139 profiles->StartProfiling("", 1, false); | |
| 140 ProfileGenerator generator(profiles); | |
| 141 ProfilerEventsProcessor processor(&generator, profiles); | |
| 142 processor.Start(); | 110 processor.Start(); |
| 143 CpuProfiler profiler(isolate, profiles, &generator, &processor); | |
| 144 | 111 |
| 145 // Enqueue code creation events. | 112 // Enqueue code creation events. |
| 113 i::HandleScope scope(isolate); |
| 146 const char* aaa_str = "aaa"; | 114 const char* aaa_str = "aaa"; |
| 147 i::Handle<i::String> aaa_name = factory->NewStringFromAscii( | 115 i::Handle<i::String> aaa_name = factory->NewStringFromAscii( |
| 148 i::Vector<const char>(aaa_str, i::StrLength(aaa_str))); | 116 i::Vector<const char>(aaa_str, i::StrLength(aaa_str))); |
| 149 profiler.CodeCreateEvent(i::Logger::FUNCTION_TAG, aaa_code, *aaa_name); | 117 processor.CodeCreateEvent(i::Logger::FUNCTION_TAG, |
| 150 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment_code, "comment"); | 118 *aaa_name, |
| 151 profiler.CodeCreateEvent(i::Logger::STUB_TAG, args5_code, 5); | 119 heap->empty_string(), |
| 152 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment2_code, "comment2"); | 120 0, |
| 153 profiler.CodeMoveEvent(comment2_code->address(), moved_code->address()); | 121 ToAddress(0x1000), |
| 154 profiler.CodeCreateEvent(i::Logger::STUB_TAG, args3_code, 3); | 122 0x100, |
| 155 profiler.CodeCreateEvent(i::Logger::STUB_TAG, args4_code, 4); | 123 ToAddress(0x10000), |
| 156 | 124 NULL); |
| 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); |
| 157 // Enqueue a tick event to enable code events processing. | 137 // Enqueue a tick event to enable code events processing. |
| 158 EnqueueTickSampleEvent(&processor, aaa_code->address()); | 138 EnqueueTickSampleEvent(&processor, ToAddress(0x1000)); |
| 159 | 139 |
| 160 processor.Stop(); | 140 processor.Stop(); |
| 161 processor.Join(); | 141 processor.Join(); |
| 162 | 142 |
| 163 // Check the state of profile generator. | 143 // Check the state of profile generator. |
| 164 CodeEntry* aaa = generator.code_map()->FindEntry(aaa_code->address()); | 144 CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000)); |
| 165 CHECK_NE(NULL, aaa); | 145 CHECK_NE(NULL, entry1); |
| 166 CHECK_EQ(aaa_str, aaa->name()); | 146 CHECK_EQ(aaa_str, entry1->name()); |
| 167 | 147 CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200)); |
| 168 CodeEntry* comment = generator.code_map()->FindEntry(comment_code->address()); | 148 CHECK_NE(NULL, entry2); |
| 169 CHECK_NE(NULL, comment); | 149 CHECK_EQ("bbb", entry2->name()); |
| 170 CHECK_EQ("comment", comment->name()); | 150 CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300)); |
| 171 | 151 CHECK_NE(NULL, entry3); |
| 172 CodeEntry* args5 = generator.code_map()->FindEntry(args5_code->address()); | 152 CHECK_EQ("5", entry3->name()); |
| 173 CHECK_NE(NULL, args5); | 153 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400))); |
| 174 CHECK_EQ("5", args5->name()); | 154 CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500)); |
| 175 | 155 CHECK_NE(NULL, entry4); |
| 176 CHECK_EQ(NULL, generator.code_map()->FindEntry(comment2_code->address())); | 156 CHECK_EQ("ddd", entry4->name()); |
| 177 | 157 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600))); |
| 178 CodeEntry* comment2 = generator.code_map()->FindEntry(moved_code->address()); | |
| 179 CHECK_NE(NULL, comment2); | |
| 180 CHECK_EQ("comment2", comment2->name()); | |
| 181 } | 158 } |
| 182 | 159 |
| 183 | 160 |
| 184 template<typename T> | 161 template<typename T> |
| 185 static int CompareProfileNodes(const T* p1, const T* p2) { | 162 static int CompareProfileNodes(const T* p1, const T* p2) { |
| 186 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name()); | 163 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name()); |
| 187 } | 164 } |
| 188 | 165 |
| 189 TEST(TickEvents) { | 166 TEST(TickEvents) { |
| 190 TestSetup test_setup; | 167 TestSetup test_setup; |
| 191 LocalContext env; | 168 CpuProfilesCollection profiles; |
| 192 i::Isolate* isolate = i::Isolate::Current(); | 169 profiles.StartProfiling("", 1, false); |
| 193 i::HandleScope scope(isolate); | 170 ProfileGenerator generator(&profiles); |
| 171 ProfilerEventsProcessor processor(&generator, &profiles); |
| 172 processor.Start(); |
| 194 | 173 |
| 195 i::Code* frame1_code = CreateCode(&env); | 174 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 196 i::Code* frame2_code = CreateCode(&env); | 175 "bbb", |
| 197 i::Code* frame3_code = CreateCode(&env); | 176 ToAddress(0x1200), |
| 198 | 177 0x80); |
| 199 CpuProfilesCollection* profiles = new CpuProfilesCollection; | 178 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10); |
| 200 profiles->StartProfiling("", 1, false); | 179 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 201 ProfileGenerator generator(profiles); | 180 "ddd", |
| 202 ProfilerEventsProcessor processor(&generator, profiles); | 181 ToAddress(0x1400), |
| 203 processor.Start(); | 182 0x80); |
| 204 CpuProfiler profiler(isolate, profiles, &generator, &processor); | 183 EnqueueTickSampleEvent(&processor, ToAddress(0x1210)); |
| 205 | 184 EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220)); |
| 206 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame1_code, "bbb"); | 185 EnqueueTickSampleEvent(&processor, |
| 207 profiler.CodeCreateEvent(i::Logger::STUB_TAG, frame2_code, 5); | 186 ToAddress(0x1404), |
| 208 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame3_code, "ddd"); | 187 ToAddress(0x1305), |
| 209 | 188 ToAddress(0x1230)); |
| 210 EnqueueTickSampleEvent(&processor, frame1_code->instruction_start()); | |
| 211 EnqueueTickSampleEvent( | |
| 212 &processor, | |
| 213 frame2_code->instruction_start() + frame2_code->ExecutableSize() / 2, | |
| 214 frame1_code->instruction_start() + frame2_code->ExecutableSize() / 2); | |
| 215 EnqueueTickSampleEvent( | |
| 216 &processor, | |
| 217 frame3_code->instruction_end() - 1, | |
| 218 frame2_code->instruction_end() - 1, | |
| 219 frame1_code->instruction_end() - 1); | |
| 220 | 189 |
| 221 processor.Stop(); | 190 processor.Stop(); |
| 222 processor.Join(); | 191 processor.Join(); |
| 223 CpuProfile* profile = | 192 CpuProfile* profile = |
| 224 profiles->StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); | 193 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); |
| 225 CHECK_NE(NULL, profile); | 194 CHECK_NE(NULL, profile); |
| 226 | 195 |
| 227 // Check call trees. | 196 // Check call trees. |
| 228 const i::List<ProfileNode*>* top_down_root_children = | 197 const i::List<ProfileNode*>* top_down_root_children = |
| 229 profile->top_down()->root()->children(); | 198 profile->top_down()->root()->children(); |
| 230 CHECK_EQ(1, top_down_root_children->length()); | 199 CHECK_EQ(1, top_down_root_children->length()); |
| 231 CHECK_EQ("bbb", top_down_root_children->last()->entry()->name()); | 200 CHECK_EQ("bbb", top_down_root_children->last()->entry()->name()); |
| 232 const i::List<ProfileNode*>* top_down_bbb_children = | 201 const i::List<ProfileNode*>* top_down_bbb_children = |
| 233 top_down_root_children->last()->children(); | 202 top_down_root_children->last()->children(); |
| 234 CHECK_EQ(1, top_down_bbb_children->length()); | 203 CHECK_EQ(1, top_down_bbb_children->length()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 253 profiler->StopProfiling("2"); | 222 profiler->StopProfiling("2"); |
| 254 profiler->StartProfiling("1"); | 223 profiler->StartProfiling("1"); |
| 255 profiler->StopProfiling(""); | 224 profiler->StopProfiling(""); |
| 256 } | 225 } |
| 257 | 226 |
| 258 | 227 |
| 259 // http://code.google.com/p/v8/issues/detail?id=1398 | 228 // http://code.google.com/p/v8/issues/detail?id=1398 |
| 260 // Long stacks (exceeding max frames limit) must not be erased. | 229 // Long stacks (exceeding max frames limit) must not be erased. |
| 261 TEST(Issue1398) { | 230 TEST(Issue1398) { |
| 262 TestSetup test_setup; | 231 TestSetup test_setup; |
| 263 LocalContext env; | 232 CpuProfilesCollection profiles; |
| 264 i::Isolate* isolate = i::Isolate::Current(); | 233 profiles.StartProfiling("", 1, false); |
| 265 i::HandleScope scope(isolate); | 234 ProfileGenerator generator(&profiles); |
| 235 ProfilerEventsProcessor processor(&generator, &profiles); |
| 236 processor.Start(); |
| 266 | 237 |
| 267 i::Code* code = CreateCode(&env); | 238 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG, |
| 268 | 239 "bbb", |
| 269 CpuProfilesCollection* profiles = new CpuProfilesCollection; | 240 ToAddress(0x1200), |
| 270 profiles->StartProfiling("", 1, false); | 241 0x80); |
| 271 ProfileGenerator generator(profiles); | |
| 272 ProfilerEventsProcessor processor(&generator, profiles); | |
| 273 processor.Start(); | |
| 274 CpuProfiler profiler(isolate, profiles, &generator, &processor); | |
| 275 | |
| 276 profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb"); | |
| 277 | 242 |
| 278 i::TickSample* sample = processor.TickSampleEvent(); | 243 i::TickSample* sample = processor.TickSampleEvent(); |
| 279 sample->pc = code->address(); | 244 sample->pc = ToAddress(0x1200); |
| 280 sample->tos = 0; | 245 sample->tos = 0; |
| 281 sample->frames_count = i::TickSample::kMaxFramesCount; | 246 sample->frames_count = i::TickSample::kMaxFramesCount; |
| 282 for (int i = 0; i < sample->frames_count; ++i) { | 247 for (int i = 0; i < sample->frames_count; ++i) { |
| 283 sample->stack[i] = code->address(); | 248 sample->stack[i] = ToAddress(0x1200); |
| 284 } | 249 } |
| 285 | 250 |
| 286 processor.Stop(); | 251 processor.Stop(); |
| 287 processor.Join(); | 252 processor.Join(); |
| 288 CpuProfile* profile = | 253 CpuProfile* profile = |
| 289 profiles->StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); | 254 profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1); |
| 290 CHECK_NE(NULL, profile); | 255 CHECK_NE(NULL, profile); |
| 291 | 256 |
| 292 int actual_depth = 0; | 257 int actual_depth = 0; |
| 293 const ProfileNode* node = profile->top_down()->root(); | 258 const ProfileNode* node = profile->top_down()->root(); |
| 294 while (node->children()->length() > 0) { | 259 while (node->children()->length() > 0) { |
| 295 node = node->children()->last(); | 260 node = node->children()->last(); |
| 296 ++actual_depth; | 261 ++actual_depth; |
| 297 } | 262 } |
| 298 | 263 |
| 299 CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth); // +1 for PC. | 264 CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth); // +1 for PC. |
| (...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); | 958 names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); |
| 994 names[2] = v8::String::New("start"); | 959 names[2] = v8::String::New("start"); |
| 995 // Don't allow |foo| node to be at the top level. | 960 // Don't allow |foo| node to be at the top level. |
| 996 CheckChildrenNames(root, names); | 961 CheckChildrenNames(root, names); |
| 997 | 962 |
| 998 const v8::CpuProfileNode* startNode = GetChild(root, "start"); | 963 const v8::CpuProfileNode* startNode = GetChild(root, "start"); |
| 999 GetChild(startNode, "foo"); | 964 GetChild(startNode, "foo"); |
| 1000 | 965 |
| 1001 cpu_profiler->DeleteAllCpuProfiles(); | 966 cpu_profiler->DeleteAllCpuProfiles(); |
| 1002 } | 967 } |
| OLD | NEW |