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