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 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 line_number); | 376 line_number); |
377 code_entries_.Add(entry); | 377 code_entries_.Add(entry); |
378 return entry; | 378 return entry; |
379 } | 379 } |
380 | 380 |
381 | 381 |
382 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, | 382 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, |
383 const char* name) { | 383 const char* name) { |
384 CodeEntry* entry = new CodeEntry(tag, | 384 CodeEntry* entry = new CodeEntry(tag, |
385 CodeEntry::kEmptyNamePrefix, | 385 CodeEntry::kEmptyNamePrefix, |
386 name, | 386 GetFunctionName(name), |
387 "", | 387 "", |
388 v8::CpuProfileNode::kNoLineNumberInfo); | 388 v8::CpuProfileNode::kNoLineNumberInfo); |
389 code_entries_.Add(entry); | 389 code_entries_.Add(entry); |
390 return entry; | 390 return entry; |
391 } | 391 } |
392 | 392 |
393 | 393 |
394 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, | 394 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag, |
395 const char* name_prefix, | 395 const char* name_prefix, |
396 String* name) { | 396 String* name) { |
(...skipping 12 matching lines...) Expand all Loading... |
409 CodeEntry* entry = new CodeEntry(tag, | 409 CodeEntry* entry = new CodeEntry(tag, |
410 "args_count: ", | 410 "args_count: ", |
411 GetName(args_count), | 411 GetName(args_count), |
412 "", | 412 "", |
413 v8::CpuProfileNode::kNoLineNumberInfo); | 413 v8::CpuProfileNode::kNoLineNumberInfo); |
414 code_entries_.Add(entry); | 414 code_entries_.Add(entry); |
415 return entry; | 415 return entry; |
416 } | 416 } |
417 | 417 |
418 | 418 |
419 const char* CpuProfilesCollection::GetFunctionName(String* name) { | |
420 const char* maybe_empty_name = GetName(name); | |
421 return strlen(maybe_empty_name) > 0 ? | |
422 maybe_empty_name : "(anonymous function)"; | |
423 } | |
424 | |
425 | |
426 const char* CpuProfilesCollection::GetName(String* name) { | 419 const char* CpuProfilesCollection::GetName(String* name) { |
427 if (name->IsString()) { | 420 if (name->IsString()) { |
428 char* c_name = | 421 char* c_name = |
429 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(); | 422 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(); |
430 HashMap::Entry* cache_entry = | 423 HashMap::Entry* cache_entry = |
431 function_and_resource_names_.Lookup(c_name, | 424 function_and_resource_names_.Lookup(c_name, |
432 name->Hash(), | 425 name->Hash(), |
433 true); | 426 true); |
434 if (cache_entry->value == NULL) { | 427 if (cache_entry->value == NULL) { |
435 // New entry added. | 428 // New entry added. |
(...skipping 30 matching lines...) Expand all Loading... |
466 // method, we don't bother minimizing the duration of lock holding, | 459 // method, we don't bother minimizing the duration of lock holding, |
467 // e.g. copying contents of the list to a local vector. | 460 // e.g. copying contents of the list to a local vector. |
468 current_profiles_semaphore_->Wait(); | 461 current_profiles_semaphore_->Wait(); |
469 for (int i = 0; i < current_profiles_.length(); ++i) { | 462 for (int i = 0; i < current_profiles_.length(); ++i) { |
470 current_profiles_[i]->AddPath(path); | 463 current_profiles_[i]->AddPath(path); |
471 } | 464 } |
472 current_profiles_semaphore_->Signal(); | 465 current_profiles_semaphore_->Signal(); |
473 } | 466 } |
474 | 467 |
475 | 468 |
| 469 const char* ProfileGenerator::kAnonymousFunctionName = "(anonymous function)"; |
| 470 const char* ProfileGenerator::kProgramEntryName = "(program)"; |
| 471 const char* ProfileGenerator::kGarbageCollectorEntryName = |
| 472 "(garbage collector)"; |
| 473 |
476 | 474 |
477 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles) | 475 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles) |
478 : profiles_(profiles), | 476 : profiles_(profiles), |
479 program_entry_( | 477 program_entry_( |
480 profiles->NewCodeEntry(Logger::FUNCTION_TAG, "(program)")) { | 478 profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)), |
| 479 gc_entry_( |
| 480 profiles->NewCodeEntry(Logger::BUILTIN_TAG, |
| 481 kGarbageCollectorEntryName)) { |
481 } | 482 } |
482 | 483 |
483 | 484 |
484 void ProfileGenerator::RecordTickSample(const TickSample& sample) { | 485 void ProfileGenerator::RecordTickSample(const TickSample& sample) { |
485 // Allocate space for stack frames + pc + function + (program). | 486 // Allocate space for stack frames + pc + function + vm-state. |
486 ScopedVector<CodeEntry*> entries(sample.frames_count + 3); | 487 ScopedVector<CodeEntry*> entries(sample.frames_count + 3); |
| 488 // As actual number of decoded code entries may vary, initialize |
| 489 // entries vector with NULL values. |
487 CodeEntry** entry = entries.start(); | 490 CodeEntry** entry = entries.start(); |
488 *entry++ = code_map_.FindEntry(sample.pc); | 491 memset(entry, 0, entries.length() * sizeof(*entry)); |
| 492 if (sample.pc != NULL) { |
| 493 *entry++ = code_map_.FindEntry(sample.pc); |
489 | 494 |
490 if (sample.function != NULL) { | 495 if (sample.function != NULL) { |
491 *entry = code_map_.FindEntry(sample.function); | 496 *entry = code_map_.FindEntry(sample.function); |
492 if (*entry != NULL && !(*entry)->is_js_function()) { | 497 if (*entry != NULL && !(*entry)->is_js_function()) { |
493 *entry = NULL; | |
494 } else { | |
495 CodeEntry* pc_entry = *entries.start(); | |
496 if (pc_entry == NULL || pc_entry->is_js_function()) | |
497 *entry = NULL; | 498 *entry = NULL; |
| 499 } else { |
| 500 CodeEntry* pc_entry = *entries.start(); |
| 501 if (pc_entry == NULL || pc_entry->is_js_function()) |
| 502 *entry = NULL; |
| 503 } |
| 504 entry++; |
498 } | 505 } |
499 entry++; | 506 |
500 } else { | 507 for (const Address *stack_pos = sample.stack, |
501 *entry++ = NULL; | 508 *stack_end = stack_pos + sample.frames_count; |
| 509 stack_pos != stack_end; |
| 510 ++stack_pos) { |
| 511 *entry++ = code_map_.FindEntry(*stack_pos); |
| 512 } |
502 } | 513 } |
503 | 514 |
504 for (const Address *stack_pos = sample.stack, | 515 if (FLAG_prof_browser_mode) { |
505 *stack_end = stack_pos + sample.frames_count; | 516 // Put VM state as the topmost entry. |
506 stack_pos != stack_end; | 517 *entry++ = EntryForVMState(sample.state); |
507 ++stack_pos) { | |
508 *entry++ = code_map_.FindEntry(*stack_pos); | |
509 } | 518 } |
510 | 519 |
511 // WebKit CPU profiles visualization requires "(program)" to be the | |
512 // topmost entry. | |
513 *entry++ = FLAG_prof_browser_mode ? program_entry_ : NULL; | |
514 | |
515 profiles_->AddPathToCurrentProfiles(entries); | 520 profiles_->AddPathToCurrentProfiles(entries); |
516 } | 521 } |
517 | 522 |
518 } } // namespace v8::internal | 523 } } // namespace v8::internal |
519 | 524 |
520 #endif // ENABLE_CPP_PROFILES_PROCESSOR | 525 #endif // ENABLE_CPP_PROFILES_PROCESSOR |
OLD | NEW |