| 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 |