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/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" |
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 entries.reserve(sample.frames_count + 3); | 601 entries.reserve(sample.frames_count + 3); |
602 | 602 |
603 // The ProfileNode knows nothing about all versions of generated code for | 603 // The ProfileNode knows nothing about all versions of generated code for |
604 // the same JS function. The line number information associated with | 604 // the same JS function. The line number information associated with |
605 // the latest version of generated code is used to find a source line number | 605 // the latest version of generated code is used to find a source line number |
606 // for a JS function. Then, the detected source line is passed to | 606 // for a JS function. Then, the detected source line is passed to |
607 // ProfileNode to increase the tick count for this source line. | 607 // ProfileNode to increase the tick count for this source line. |
608 int src_line = v8::CpuProfileNode::kNoLineNumberInfo; | 608 int src_line = v8::CpuProfileNode::kNoLineNumberInfo; |
609 bool src_line_not_found = true; | 609 bool src_line_not_found = true; |
610 | 610 |
611 if (sample.pc != nullptr) { | 611 if (sample.pc != NULL) { |
612 if (sample.has_external_callback && sample.state == EXTERNAL) { | 612 if (sample.has_external_callback && sample.state == EXTERNAL && |
| 613 sample.top_frame_type == StackFrame::EXIT) { |
613 // Don't use PC when in external callback code, as it can point | 614 // Don't use PC when in external callback code, as it can point |
614 // inside callback's code, and we will erroneously report | 615 // inside callback's code, and we will erroneously report |
615 // that a callback calls itself. | 616 // that a callback calls itself. |
616 entries.push_back(code_map_.FindEntry(sample.external_callback_entry)); | 617 entries.push_back(code_map_.FindEntry(sample.external_callback_entry)); |
617 } else { | 618 } else { |
618 CodeEntry* pc_entry = code_map_.FindEntry(sample.pc); | 619 CodeEntry* pc_entry = code_map_.FindEntry(sample.pc); |
619 // If there is no pc_entry we're likely in native code. | 620 // If there is no pc_entry we're likely in native code. |
620 // Find out, if top of stack was pointing inside a JS function | 621 // Find out, if top of stack was pointing inside a JS function |
621 // meaning that we have encountered a frameless invocation. | 622 // meaning that we have encountered a frameless invocation. |
622 if (!pc_entry && !sample.has_external_callback) { | 623 if (!pc_entry && (sample.top_frame_type == StackFrame::JAVA_SCRIPT || |
| 624 sample.top_frame_type == StackFrame::INTERPRETED || |
| 625 sample.top_frame_type == StackFrame::OPTIMIZED)) { |
623 pc_entry = code_map_.FindEntry(sample.tos); | 626 pc_entry = code_map_.FindEntry(sample.tos); |
624 } | 627 } |
625 // If pc is in the function code before it set up stack frame or after the | 628 // If pc is in the function code before it set up stack frame or after the |
626 // frame was destroyed SafeStackFrameIterator incorrectly thinks that | 629 // frame was destroyed SafeStackFrameIterator incorrectly thinks that |
627 // ebp contains return address of the current function and skips caller's | 630 // ebp contains return address of the current function and skips caller's |
628 // frame. Check for this case and just skip such samples. | 631 // frame. Check for this case and just skip such samples. |
629 if (pc_entry) { | 632 if (pc_entry) { |
630 int pc_offset = | 633 int pc_offset = |
631 static_cast<int>(sample.pc - pc_entry->instruction_start()); | 634 static_cast<int>(sample.pc - pc_entry->instruction_start()); |
632 src_line = pc_entry->GetSourceLine(pc_offset); | 635 src_line = pc_entry->GetSourceLine(pc_offset); |
633 if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) { | 636 if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) { |
634 src_line = pc_entry->line_number(); | 637 src_line = pc_entry->line_number(); |
635 } | 638 } |
636 src_line_not_found = false; | 639 src_line_not_found = false; |
637 entries.push_back(pc_entry); | 640 entries.push_back(pc_entry); |
638 | 641 |
639 if (pc_entry->builtin_id() == Builtins::kFunctionPrototypeApply || | 642 if (pc_entry->builtin_id() == Builtins::kFunctionPrototypeApply || |
640 pc_entry->builtin_id() == Builtins::kFunctionPrototypeCall) { | 643 pc_entry->builtin_id() == Builtins::kFunctionPrototypeCall) { |
641 // When current function is either the Function.prototype.apply or the | 644 // When current function is either the Function.prototype.apply or the |
642 // Function.prototype.call builtin the top frame is either frame of | 645 // Function.prototype.call builtin the top frame is either frame of |
643 // the calling JS function or internal frame. | 646 // the calling JS function or internal frame. |
644 // In the latter case we know the caller for sure but in the | 647 // In the latter case we know the caller for sure but in the |
645 // former case we don't so we simply replace the frame with | 648 // former case we don't so we simply replace the frame with |
646 // 'unresolved' entry. | 649 // 'unresolved' entry. |
647 if (!sample.has_external_callback) { | 650 if (sample.top_frame_type == StackFrame::JAVA_SCRIPT) { |
648 entries.push_back(unresolved_entry_); | 651 entries.push_back(unresolved_entry_); |
649 } | 652 } |
650 } | 653 } |
651 } | 654 } |
652 } | 655 } |
653 | 656 |
654 for (const Address *stack_pos = sample.stack, | 657 for (const Address *stack_pos = sample.stack, |
655 *stack_end = stack_pos + sample.frames_count; | 658 *stack_end = stack_pos + sample.frames_count; |
656 stack_pos != stack_end; ++stack_pos) { | 659 stack_pos != stack_end; ++stack_pos) { |
657 CodeEntry* entry = code_map_.FindEntry(*stack_pos); | 660 CodeEntry* entry = code_map_.FindEntry(*stack_pos); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 case EXTERNAL: | 715 case EXTERNAL: |
713 return program_entry_; | 716 return program_entry_; |
714 case IDLE: | 717 case IDLE: |
715 return idle_entry_; | 718 return idle_entry_; |
716 default: return NULL; | 719 default: return NULL; |
717 } | 720 } |
718 } | 721 } |
719 | 722 |
720 } // namespace internal | 723 } // namespace internal |
721 } // namespace v8 | 724 } // namespace v8 |
OLD | NEW |