OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/profiler/cpu-profiler.h" | 5 #include "src/profiler/cpu-profiler.h" |
6 | 6 |
7 #include "src/debug/debug.h" | 7 #include "src/debug/debug.h" |
8 #include "src/deoptimizer.h" | 8 #include "src/deoptimizer.h" |
9 #include "src/frames-inl.h" | 9 #include "src/frames-inl.h" |
10 #include "src/locked-queue-inl.h" | 10 #include "src/locked-queue-inl.h" |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 | 213 |
214 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, | 214 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, |
215 AbstractCode* code, const char* name) { | 215 AbstractCode* code, const char* name) { |
216 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); | 216 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); |
217 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; | 217 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; |
218 rec->start = code->address(); | 218 rec->start = code->address(); |
219 rec->entry = profiles_->NewCodeEntry( | 219 rec->entry = profiles_->NewCodeEntry( |
220 tag, profiles_->GetFunctionName(name), CodeEntry::kEmptyNamePrefix, | 220 tag, profiles_->GetFunctionName(name), CodeEntry::kEmptyNamePrefix, |
221 CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo, | 221 CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo, |
222 CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start()); | 222 CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start()); |
| 223 RecordInliningInfo(rec->entry, code); |
223 rec->size = code->ExecutableSize(); | 224 rec->size = code->ExecutableSize(); |
224 processor_->Enqueue(evt_rec); | 225 processor_->Enqueue(evt_rec); |
225 } | 226 } |
226 | 227 |
227 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, | 228 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, |
228 AbstractCode* code, Name* name) { | 229 AbstractCode* code, Name* name) { |
229 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); | 230 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); |
230 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; | 231 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; |
231 rec->start = code->address(); | 232 rec->start = code->address(); |
232 rec->entry = profiles_->NewCodeEntry( | 233 rec->entry = profiles_->NewCodeEntry( |
233 tag, profiles_->GetFunctionName(name), CodeEntry::kEmptyNamePrefix, | 234 tag, profiles_->GetFunctionName(name), CodeEntry::kEmptyNamePrefix, |
234 CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo, | 235 CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo, |
235 CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start()); | 236 CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start()); |
| 237 RecordInliningInfo(rec->entry, code); |
236 rec->size = code->ExecutableSize(); | 238 rec->size = code->ExecutableSize(); |
237 processor_->Enqueue(evt_rec); | 239 processor_->Enqueue(evt_rec); |
238 } | 240 } |
239 | 241 |
240 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, | 242 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, |
241 AbstractCode* code, | 243 AbstractCode* code, |
242 SharedFunctionInfo* shared, | 244 SharedFunctionInfo* shared, |
243 CompilationInfo* info, Name* script_name) { | 245 CompilationInfo* info, Name* script_name) { |
244 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); | 246 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); |
245 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; | 247 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; |
246 rec->start = code->address(); | 248 rec->start = code->address(); |
247 rec->entry = profiles_->NewCodeEntry( | 249 rec->entry = profiles_->NewCodeEntry( |
248 tag, profiles_->GetFunctionName(shared->DebugName()), | 250 tag, profiles_->GetFunctionName(shared->DebugName()), |
249 CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name), | 251 CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name), |
250 CpuProfileNode::kNoLineNumberInfo, CpuProfileNode::kNoColumnNumberInfo, | 252 CpuProfileNode::kNoLineNumberInfo, CpuProfileNode::kNoColumnNumberInfo, |
251 NULL, code->instruction_start()); | 253 NULL, code->instruction_start()); |
| 254 RecordInliningInfo(rec->entry, code); |
252 if (info) { | 255 if (info) { |
253 rec->entry->set_inlined_function_infos(info->inlined_function_infos()); | 256 rec->entry->set_inlined_function_infos(info->inlined_function_infos()); |
254 } | 257 } |
255 rec->entry->FillFunctionInfo(shared); | 258 rec->entry->FillFunctionInfo(shared); |
256 rec->size = code->ExecutableSize(); | 259 rec->size = code->ExecutableSize(); |
257 processor_->Enqueue(evt_rec); | 260 processor_->Enqueue(evt_rec); |
258 } | 261 } |
259 | 262 |
260 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, | 263 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, |
261 AbstractCode* abstract_code, | 264 AbstractCode* abstract_code, |
(...skipping 23 matching lines...) Expand all Loading... |
285 } | 288 } |
286 } else { | 289 } else { |
287 DCHECK(abstract_code->IsBytecodeArray()); | 290 DCHECK(abstract_code->IsBytecodeArray()); |
288 // TODO(rmcilroy): source position tracking for bytecode arrays. | 291 // TODO(rmcilroy): source position tracking for bytecode arrays. |
289 } | 292 } |
290 } | 293 } |
291 rec->entry = profiles_->NewCodeEntry( | 294 rec->entry = profiles_->NewCodeEntry( |
292 tag, profiles_->GetFunctionName(shared->DebugName()), | 295 tag, profiles_->GetFunctionName(shared->DebugName()), |
293 CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name), line, | 296 CodeEntry::kEmptyNamePrefix, profiles_->GetName(script_name), line, |
294 column, line_table, abstract_code->instruction_start()); | 297 column, line_table, abstract_code->instruction_start()); |
| 298 RecordInliningInfo(rec->entry, abstract_code); |
295 if (info) { | 299 if (info) { |
296 rec->entry->set_inlined_function_infos(info->inlined_function_infos()); | 300 rec->entry->set_inlined_function_infos(info->inlined_function_infos()); |
297 } | 301 } |
298 rec->entry->FillFunctionInfo(shared); | 302 rec->entry->FillFunctionInfo(shared); |
299 rec->size = abstract_code->ExecutableSize(); | 303 rec->size = abstract_code->ExecutableSize(); |
300 processor_->Enqueue(evt_rec); | 304 processor_->Enqueue(evt_rec); |
301 } | 305 } |
302 | 306 |
303 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, | 307 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag, |
304 AbstractCode* code, int args_count) { | 308 AbstractCode* code, int args_count) { |
305 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); | 309 CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); |
306 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; | 310 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; |
307 rec->start = code->address(); | 311 rec->start = code->address(); |
308 rec->entry = profiles_->NewCodeEntry( | 312 rec->entry = profiles_->NewCodeEntry( |
309 tag, profiles_->GetName(args_count), "args_count: ", | 313 tag, profiles_->GetName(args_count), "args_count: ", |
310 CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo, | 314 CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo, |
311 CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start()); | 315 CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start()); |
| 316 RecordInliningInfo(rec->entry, code); |
312 rec->size = code->ExecutableSize(); | 317 rec->size = code->ExecutableSize(); |
313 processor_->Enqueue(evt_rec); | 318 processor_->Enqueue(evt_rec); |
314 } | 319 } |
315 | 320 |
316 void CpuProfiler::CodeMoveEvent(AbstractCode* from, Address to) { | 321 void CpuProfiler::CodeMoveEvent(AbstractCode* from, Address to) { |
317 CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE); | 322 CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE); |
318 CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_; | 323 CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_; |
319 rec->from = from->address(); | 324 rec->from = from->address(); |
320 rec->to = to; | 325 rec->to = to; |
321 processor_->Enqueue(evt_rec); | 326 processor_->Enqueue(evt_rec); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; | 377 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; |
373 rec->start = entry_point; | 378 rec->start = entry_point; |
374 rec->entry = profiles_->NewCodeEntry( | 379 rec->entry = profiles_->NewCodeEntry( |
375 Logger::CALLBACK_TAG, | 380 Logger::CALLBACK_TAG, |
376 profiles_->GetName(name), | 381 profiles_->GetName(name), |
377 "set "); | 382 "set "); |
378 rec->size = 1; | 383 rec->size = 1; |
379 processor_->Enqueue(evt_rec); | 384 processor_->Enqueue(evt_rec); |
380 } | 385 } |
381 | 386 |
| 387 void CpuProfiler::RecordInliningInfo(CodeEntry* entry, |
| 388 AbstractCode* abstract_code) { |
| 389 if (!abstract_code->IsCode()) return; |
| 390 Code* code = abstract_code->GetCode(); |
| 391 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; |
| 392 DeoptimizationInputData* deopt_input_data = |
| 393 DeoptimizationInputData::cast(code->deoptimization_data()); |
| 394 int deopt_count = deopt_input_data->DeoptCount(); |
| 395 for (int i = 0; i < deopt_count; i++) { |
| 396 int pc_offset = deopt_input_data->Pc(i)->value(); |
| 397 if (pc_offset == -1) continue; |
| 398 int translation_index = deopt_input_data->TranslationIndex(i)->value(); |
| 399 TranslationIterator it(deopt_input_data->TranslationByteArray(), |
| 400 translation_index); |
| 401 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
| 402 DCHECK_EQ(Translation::BEGIN, opcode); |
| 403 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
| 404 int depth = 0; |
| 405 std::vector<CodeEntry*> inline_stack; |
| 406 while (it.HasNext() && |
| 407 Translation::BEGIN != |
| 408 (opcode = static_cast<Translation::Opcode>(it.Next()))) { |
| 409 if (opcode != Translation::JS_FRAME && |
| 410 opcode != Translation::INTERPRETED_FRAME) { |
| 411 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
| 412 continue; |
| 413 } |
| 414 it.Next(); // Skip ast_id |
| 415 int shared_info_id = it.Next(); |
| 416 it.Next(); // Skip height |
| 417 SharedFunctionInfo* shared_info = SharedFunctionInfo::cast( |
| 418 deopt_input_data->LiteralArray()->get(shared_info_id)); |
| 419 if (!depth++) continue; // Skip the current function itself. |
| 420 CodeEntry* inline_entry = new CodeEntry( |
| 421 entry->tag(), profiles_->GetFunctionName(shared_info->DebugName()), |
| 422 CodeEntry::kEmptyNamePrefix, entry->resource_name(), |
| 423 CpuProfileNode::kNoLineNumberInfo, |
| 424 CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start()); |
| 425 inline_entry->FillFunctionInfo(shared_info); |
| 426 inline_stack.push_back(inline_entry); |
| 427 } |
| 428 if (!inline_stack.empty()) { |
| 429 entry->AddInlineStack(pc_offset, inline_stack); |
| 430 DCHECK(inline_stack.empty()); |
| 431 } |
| 432 } |
| 433 } |
382 | 434 |
383 CpuProfiler::CpuProfiler(Isolate* isolate) | 435 CpuProfiler::CpuProfiler(Isolate* isolate) |
384 : isolate_(isolate), | 436 : isolate_(isolate), |
385 sampling_interval_(base::TimeDelta::FromMicroseconds( | 437 sampling_interval_(base::TimeDelta::FromMicroseconds( |
386 FLAG_cpu_profiler_sampling_interval)), | 438 FLAG_cpu_profiler_sampling_interval)), |
387 profiles_(new CpuProfilesCollection(isolate->heap())), | 439 profiles_(new CpuProfilesCollection(isolate->heap())), |
388 generator_(NULL), | 440 generator_(NULL), |
389 processor_(NULL), | 441 processor_(NULL), |
390 is_profiling_(false) { | 442 is_profiling_(false) { |
391 } | 443 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 Builtins::Name id = static_cast<Builtins::Name>(i); | 571 Builtins::Name id = static_cast<Builtins::Name>(i); |
520 rec->start = builtins->builtin(id)->address(); | 572 rec->start = builtins->builtin(id)->address(); |
521 rec->builtin_id = id; | 573 rec->builtin_id = id; |
522 processor_->Enqueue(evt_rec); | 574 processor_->Enqueue(evt_rec); |
523 } | 575 } |
524 } | 576 } |
525 | 577 |
526 | 578 |
527 } // namespace internal | 579 } // namespace internal |
528 } // namespace v8 | 580 } // namespace v8 |
OLD | NEW |