Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(469)

Side by Side Diff: src/profiler/profile-generator.cc

Issue 2105943002: Expose TickSample and its APIs in v8-profiler.h (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/profile-generator.h" 5 #include "src/profiler/profile-generator.h"
6 6
7 #include "src/ast/scopeinfo.h" 7 #include "src/ast/scopeinfo.h"
8 #include "src/base/adapters.h" 8 #include "src/base/adapters.h"
9 #include "src/debug/debug.h" 9 #include "src/debug/debug.h"
10 #include "src/deoptimizer.h" 10 #include "src/deoptimizer.h"
11 #include "src/global-handles.h" 11 #include "src/global-handles.h"
12 #include "src/profiler/cpu-profiler.h" 12 #include "src/profiler/cpu-profiler.h"
13 #include "src/profiler/profile-generator-inl.h" 13 #include "src/profiler/profile-generator-inl.h"
14 #include "src/profiler/tick-sample.h"
15 #include "src/unicode.h" 14 #include "src/unicode.h"
16 15
17 namespace v8 { 16 namespace v8 {
18 namespace internal { 17 namespace internal {
19 18
20 19
21 JITLineInfoTable::JITLineInfoTable() {} 20 JITLineInfoTable::JITLineInfoTable() {}
22 21
23 22
24 JITLineInfoTable::~JITLineInfoTable() {} 23 JITLineInfoTable::~JITLineInfoTable() {}
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 current_profiles_semaphore_.Wait(); 551 current_profiles_semaphore_.Wait();
553 for (int i = 0; i < current_profiles_.length(); ++i) { 552 for (int i = 0; i < current_profiles_.length(); ++i) {
554 current_profiles_[i]->AddPath(timestamp, path, src_line, update_stats); 553 current_profiles_[i]->AddPath(timestamp, path, src_line, update_stats);
555 } 554 }
556 current_profiles_semaphore_.Signal(); 555 current_profiles_semaphore_.Signal();
557 } 556 }
558 557
559 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles) 558 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
560 : profiles_(profiles) {} 559 : profiles_(profiles) {}
561 560
562 void ProfileGenerator::RecordTickSample(const TickSample& sample) { 561 void ProfileGenerator::RecordTickSample(const TickSample& sample,
562 const base::TimeTicks& timestamp) {
563 std::vector<CodeEntry*> entries; 563 std::vector<CodeEntry*> entries;
564 // Conservatively reserve space for stack frames + pc + function + vm-state. 564 // Conservatively reserve space for stack frames + pc + function + vm-state.
565 // There could in fact be more of them because of inlined entries. 565 // There could in fact be more of them because of inlined entries.
566 entries.reserve(sample.frames_count + 3); 566 entries.reserve(sample.frames_count + 3);
567 567
568 // The ProfileNode knows nothing about all versions of generated code for 568 // The ProfileNode knows nothing about all versions of generated code for
569 // the same JS function. The line number information associated with 569 // the same JS function. The line number information associated with
570 // the latest version of generated code is used to find a source line number 570 // the latest version of generated code is used to find a source line number
571 // for a JS function. Then, the detected source line is passed to 571 // for a JS function. Then, the detected source line is passed to
572 // ProfileNode to increase the tick count for this source line. 572 // ProfileNode to increase the tick count for this source line.
573 int src_line = v8::CpuProfileNode::kNoLineNumberInfo; 573 int src_line = v8::CpuProfileNode::kNoLineNumberInfo;
574 bool src_line_not_found = true; 574 bool src_line_not_found = true;
575 575
576 if (sample.pc != nullptr) { 576 if (sample.pc != nullptr) {
577 if (sample.has_external_callback && sample.state == EXTERNAL) { 577 if (sample.has_external_callback && sample.state == EXTERNAL) {
578 // Don't use PC when in external callback code, as it can point 578 // Don't use PC when in external callback code, as it can point
579 // inside callback's code, and we will erroneously report 579 // inside callback's code, and we will erroneously report
580 // that a callback calls itself. 580 // that a callback calls itself.
581 entries.push_back(code_map_.FindEntry(sample.external_callback_entry)); 581 entries.push_back(code_map_.FindEntry(
582 reinterpret_cast<Address>(sample.external_callback_entry)));
582 } else { 583 } else {
583 CodeEntry* pc_entry = code_map_.FindEntry(sample.pc); 584 CodeEntry* pc_entry =
585 code_map_.FindEntry(reinterpret_cast<Address>(sample.pc));
584 // If there is no pc_entry we're likely in native code. 586 // If there is no pc_entry we're likely in native code.
585 // Find out, if top of stack was pointing inside a JS function 587 // Find out, if top of stack was pointing inside a JS function
586 // meaning that we have encountered a frameless invocation. 588 // meaning that we have encountered a frameless invocation.
587 if (!pc_entry && !sample.has_external_callback) { 589 if (!pc_entry && !sample.has_external_callback) {
588 pc_entry = code_map_.FindEntry(sample.tos); 590 pc_entry = code_map_.FindEntry(reinterpret_cast<Address>(sample.tos));
589 } 591 }
590 // If pc is in the function code before it set up stack frame or after the 592 // If pc is in the function code before it set up stack frame or after the
591 // frame was destroyed SafeStackFrameIterator incorrectly thinks that 593 // frame was destroyed SafeStackFrameIterator incorrectly thinks that
592 // ebp contains return address of the current function and skips caller's 594 // ebp contains return address of the current function and skips caller's
593 // frame. Check for this case and just skip such samples. 595 // frame. Check for this case and just skip such samples.
594 if (pc_entry) { 596 if (pc_entry) {
595 int pc_offset = 597 int pc_offset = static_cast<int>(reinterpret_cast<Address>(sample.pc) -
596 static_cast<int>(sample.pc - pc_entry->instruction_start()); 598 pc_entry->instruction_start());
597 src_line = pc_entry->GetSourceLine(pc_offset); 599 src_line = pc_entry->GetSourceLine(pc_offset);
598 if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) { 600 if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) {
599 src_line = pc_entry->line_number(); 601 src_line = pc_entry->line_number();
600 } 602 }
601 src_line_not_found = false; 603 src_line_not_found = false;
602 entries.push_back(pc_entry); 604 entries.push_back(pc_entry);
603 605
604 if (pc_entry->builtin_id() == Builtins::kFunctionPrototypeApply || 606 if (pc_entry->builtin_id() == Builtins::kFunctionPrototypeApply ||
605 pc_entry->builtin_id() == Builtins::kFunctionPrototypeCall) { 607 pc_entry->builtin_id() == Builtins::kFunctionPrototypeCall) {
606 // When current function is either the Function.prototype.apply or the 608 // When current function is either the Function.prototype.apply or the
607 // Function.prototype.call builtin the top frame is either frame of 609 // Function.prototype.call builtin the top frame is either frame of
608 // the calling JS function or internal frame. 610 // the calling JS function or internal frame.
609 // In the latter case we know the caller for sure but in the 611 // In the latter case we know the caller for sure but in the
610 // former case we don't so we simply replace the frame with 612 // former case we don't so we simply replace the frame with
611 // 'unresolved' entry. 613 // 'unresolved' entry.
612 if (!sample.has_external_callback) { 614 if (!sample.has_external_callback) {
613 entries.push_back(CodeEntry::unresolved_entry()); 615 entries.push_back(CodeEntry::unresolved_entry());
614 } 616 }
615 } 617 }
616 } 618 }
617 } 619 }
618 620
619 for (const Address *stack_pos = sample.stack, 621 for (unsigned i = 0; i < sample.frames_count; ++i) {
620 *stack_end = stack_pos + sample.frames_count; 622 Address stack_pos = reinterpret_cast<Address>(sample.stack[i]);
621 stack_pos != stack_end; ++stack_pos) { 623 CodeEntry* entry = code_map_.FindEntry(stack_pos);
622 CodeEntry* entry = code_map_.FindEntry(*stack_pos);
623 624
624 if (entry) { 625 if (entry) {
625 // Find out if the entry has an inlining stack associated. 626 // Find out if the entry has an inlining stack associated.
626 int pc_offset = 627 int pc_offset =
627 static_cast<int>(*stack_pos - entry->instruction_start()); 628 static_cast<int>(stack_pos - entry->instruction_start());
628 const std::vector<CodeEntry*>* inline_stack = 629 const std::vector<CodeEntry*>* inline_stack =
629 entry->GetInlineStack(pc_offset); 630 entry->GetInlineStack(pc_offset);
630 if (inline_stack) { 631 if (inline_stack) {
631 entries.insert(entries.end(), inline_stack->rbegin(), 632 entries.insert(entries.end(), inline_stack->rbegin(),
632 inline_stack->rend()); 633 inline_stack->rend());
633 } 634 }
634 // Skip unresolved frames (e.g. internal frame) and get source line of 635 // Skip unresolved frames (e.g. internal frame) and get source line of
635 // the first JS caller. 636 // the first JS caller.
636 if (src_line_not_found) { 637 if (src_line_not_found) {
637 src_line = entry->GetSourceLine(pc_offset); 638 src_line = entry->GetSourceLine(pc_offset);
(...skipping 14 matching lines...) Expand all
652 no_symbolized_entries = false; 653 no_symbolized_entries = false;
653 break; 654 break;
654 } 655 }
655 } 656 }
656 // If no frames were symbolized, put the VM state entry in. 657 // If no frames were symbolized, put the VM state entry in.
657 if (no_symbolized_entries) { 658 if (no_symbolized_entries) {
658 entries.push_back(EntryForVMState(sample.state)); 659 entries.push_back(EntryForVMState(sample.state));
659 } 660 }
660 } 661 }
661 662
662 profiles_->AddPathToCurrentProfiles(sample.timestamp, entries, src_line, 663 profiles_->AddPathToCurrentProfiles(timestamp, entries, src_line,
663 sample.update_stats); 664 sample.update_stats);
664 } 665 }
665 666
666 667
667 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) { 668 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
668 switch (tag) { 669 switch (tag) {
669 case GC: 670 case GC:
670 return CodeEntry::gc_entry(); 671 return CodeEntry::gc_entry();
671 case JS: 672 case JS:
672 case COMPILER: 673 case COMPILER:
673 // DOM events handlers are reported as OTHER / EXTERNAL entries. 674 // DOM events handlers are reported as OTHER / EXTERNAL entries.
674 // To avoid confusing people, let's put all these entries into 675 // To avoid confusing people, let's put all these entries into
675 // one bucket. 676 // one bucket.
676 case OTHER: 677 case OTHER:
677 case EXTERNAL: 678 case EXTERNAL:
678 return CodeEntry::program_entry(); 679 return CodeEntry::program_entry();
679 case IDLE: 680 case IDLE:
680 return CodeEntry::idle_entry(); 681 return CodeEntry::idle_entry();
681 default: return NULL; 682 default: return NULL;
682 } 683 }
683 } 684 }
684 685
685 } // namespace internal 686 } // namespace internal
686 } // namespace v8 687 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698