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

Side by Side Diff: runtime/vm/profiler.cc

Issue 264933006: Fix edge case where profiler would miss the caller of the top frame (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 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 | Annotate | Revision Log
« runtime/vm/profiler.h ('K') | « runtime/vm/profiler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/utils.h" 5 #include "platform/utils.h"
6 6
7 #include "vm/allocation.h" 7 #include "vm/allocation.h"
8 #include "vm/atomic.h" 8 #include "vm/atomic.h"
9 #include "vm/code_patcher.h" 9 #include "vm/code_patcher.h"
10 #include "vm/isolate.h" 10 #include "vm/isolate.h"
(...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 !b->contains(a->end() - 1)); 903 !b->contains(a->end() - 1));
904 } 904 }
905 } 905 }
906 } 906 }
907 #endif 907 #endif
908 908
909 ZoneGrowableArray<CodeRegion*>* code_region_table_; 909 ZoneGrowableArray<CodeRegion*>* code_region_table_;
910 }; 910 };
911 911
912 912
913 class FixTopFrameVisitor : public SampleVisitor {
srdjan 2014/05/02 18:20:29 Make SampleVisitor a ValueObject if possible so th
Cutch 2014/05/02 18:37:03 Done.
914 public:
915 explicit FixTopFrameVisitor(Isolate* isolate)
916 : SampleVisitor(isolate),
917 code_(Code::Handle(isolate)),
918 vm_isolate_(Dart::vm_isolate()) {
919 }
920
921 void VisitSample(Sample* sample) {
922 if (sample->processed()) {
923 // Already processed.
924 return;
925 }
926 // Mark that we've processed this sample.
927 sample->set_processed(true);
928 // Lookup code object for leaf frame.
929 code_ = FindCodeForPC(sample->At(0));
930 sample->set_leaf_frame_is_dart(!code_.IsNull());
931 if (!code_.IsNull() && (code_.compile_timestamp() > sample->timestamp())) {
932 // Code compiled after sample. Ignore.
933 return;
934 }
935 if (sample->leaf_frame_is_dart()) {
936 FixMissingDartFrame(sample);
937 }
938 }
939
940 private:
941 void FixMissingDartFrame(Sample* sample) {
srdjan 2014/05/02 18:20:29 s/FixMissingDartFrame/CheckForMissingDartFrame/
Cutch 2014/05/02 18:37:03 Done.
942 // Some stubs (and intrinsics) do not push a frame onto the stack leaving
943 // the frame pointer in the caller.
944 //
945 // PC -> STUB
946 // FP -> DART3 <-+
947 // DART2 <-| <- TOP FRAME RETURN ADDRESS.
948 // DART1 <-|
949 // .....
950 //
951 // In this case, traversing the linked stack frames will not collect a PC
952 // inside DART3. The stack will incorrectly be: STUB, DART2, DART1.
953 // In Dart code, after pushing the FP onto the stack, an IP in the current
954 // function is pushed onto the stack as well. This stack slot is called
955 // the PC marker. We can use the PC marker to insert DART3 into the stack
956 // so that it will correctly be: STUB, DART3, DART2, DART1. Note the
957 // inserted PC may not accurately reflect the true return address from STUB.
958 ASSERT(!code_.IsNull());
959 if (sample->sp() == sample->fp()) {
960 // Haven't pushed pc marker yet.
961 return;
962 }
963 uword pc_marker = sample->pc_marker();
964 if (code_.ContainsInstructionAt(pc_marker)) {
965 // PC marker is in the same code as pc, no missing frame.
966 return;
967 }
968 if (!ContainedInDartCodeHeaps(pc_marker)) {
969 // Not a valid PC marker.
970 return;
971 }
972 sample->InsertCallerForTopFrame(pc_marker);
973 }
974
975 bool ContainedInDartCodeHeaps(uword pc) {
976 return isolate()->heap()->CodeContains(pc) ||
977 vm_isolate()->heap()->CodeContains(pc);
978 }
979
980 Isolate* vm_isolate() const {
981 return vm_isolate_;
982 }
983
984 RawCode* FindCodeForPC(uword pc) {
985 // Check current isolate for pc.
986 if (isolate()->heap()->CodeContains(pc)) {
987 return Code::LookupCode(pc);
988 }
989 // Check VM isolate for pc.
990 if (vm_isolate()->heap()->CodeContains(pc)) {
991 return Code::LookupCodeInVmIsolate(pc);
992 }
993 return Code::null();
994 }
995
996 Code& code_;
srdjan 2014/05/02 18:20:29 Code*. We try to use reference with const.
997
998 Isolate* vm_isolate_;
999 };
1000
1001
913 class CodeRegionTableBuilder : public SampleVisitor { 1002 class CodeRegionTableBuilder : public SampleVisitor {
914 public: 1003 public:
915 CodeRegionTableBuilder(Isolate* isolate, 1004 CodeRegionTableBuilder(Isolate* isolate,
916 CodeRegionTable* live_code_table, 1005 CodeRegionTable* live_code_table,
917 CodeRegionTable* dead_code_table, 1006 CodeRegionTable* dead_code_table,
918 CodeRegionTable* tag_code_table) 1007 CodeRegionTable* tag_code_table)
919 : SampleVisitor(isolate), 1008 : SampleVisitor(isolate),
920 live_code_table_(live_code_table), 1009 live_code_table_(live_code_table),
921 dead_code_table_(dead_code_table), 1010 dead_code_table_(dead_code_table),
922 tag_code_table_(tag_code_table), 1011 tag_code_table_(tag_code_table),
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
1349 CodeRegionTable live_code_table; 1438 CodeRegionTable live_code_table;
1350 // Dead code holds Overwritten CodeRegions. 1439 // Dead code holds Overwritten CodeRegions.
1351 CodeRegionTable dead_code_table; 1440 CodeRegionTable dead_code_table;
1352 // Tag code holds Tag CodeRegions. 1441 // Tag code holds Tag CodeRegions.
1353 CodeRegionTable tag_code_table; 1442 CodeRegionTable tag_code_table;
1354 CodeRegionTableBuilder builder(isolate, 1443 CodeRegionTableBuilder builder(isolate,
1355 &live_code_table, 1444 &live_code_table,
1356 &dead_code_table, 1445 &dead_code_table,
1357 &tag_code_table); 1446 &tag_code_table);
1358 { 1447 {
1448 // Preprocess samples and fix the caller when the top PC is in a
1449 // stub or intrinsic without a frame.
1450 FixTopFrameVisitor fixTopFrame(isolate);
1451 sample_buffer->VisitSamplesByReference(&fixTopFrame);
1452 }
1453 {
1359 // Build CodeRegion tables. 1454 // Build CodeRegion tables.
1360 ScopeStopwatch sw("CodeRegionTableBuilder"); 1455 ScopeStopwatch sw("CodeRegionTableBuilder");
1361 sample_buffer->VisitSamples(&builder); 1456 sample_buffer->VisitSamples(&builder);
1362 } 1457 }
1363 intptr_t samples = builder.visited(); 1458 intptr_t samples = builder.visited();
1364 intptr_t frames = builder.frames(); 1459 intptr_t frames = builder.frames();
1365 if (FLAG_trace_profiled_isolates) { 1460 if (FLAG_trace_profiled_isolates) {
1366 intptr_t total_live_code_objects = live_code_table.Length(); 1461 intptr_t total_live_code_objects = live_code_table.Length();
1367 intptr_t total_dead_code_objects = dead_code_table.Length(); 1462 intptr_t total_dead_code_objects = dead_code_table.Length();
1368 intptr_t total_tag_code_objects = tag_code_table.Length(); 1463 intptr_t total_tag_code_objects = tag_code_table.Length();
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
1593 if (gap >= kMaxStep) { 1688 if (gap >= kMaxStep) {
1594 // Gap between frame pointer and stack pointer is 1689 // Gap between frame pointer and stack pointer is
1595 // too large. 1690 // too large.
1596 return 1; 1691 return 1;
1597 } 1692 }
1598 if (original_sp_ < lower_bound_) { 1693 if (original_sp_ < lower_bound_) {
1599 // The stack pointer gives us a better lower bound than 1694 // The stack pointer gives us a better lower bound than
1600 // the isolates stack limit. 1695 // the isolates stack limit.
1601 lower_bound_ = original_sp_; 1696 lower_bound_ = original_sp_;
1602 } 1697 }
1698 // Store the PC marker for the top frame.
1699 sample_->set_pc_marker(GetCurrentFramePcMarker(fp));
1603 int i = 0; 1700 int i = 0;
1604 for (; i < FLAG_profile_depth; i++) { 1701 for (; i < FLAG_profile_depth; i++) {
1605 if (FLAG_profile_verify_stack_walk) { 1702 if (FLAG_profile_verify_stack_walk) {
1606 VerifyCodeAddress(heap, i, reinterpret_cast<uword>(pc)); 1703 VerifyCodeAddress(heap, i, reinterpret_cast<uword>(pc));
1607 } 1704 }
1608 sample_->SetAt(i, reinterpret_cast<uword>(pc)); 1705 sample_->SetAt(i, reinterpret_cast<uword>(pc));
1609 if (fp == NULL) { 1706 if (fp == NULL) {
1610 return i + 1; 1707 return i + 1;
1611 } 1708 }
1612 if (!ValidFramePointer(fp)) { 1709 if (!ValidFramePointer(fp)) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1655 uword* CallerPC(uword* fp) const { 1752 uword* CallerPC(uword* fp) const {
1656 ASSERT(fp != NULL); 1753 ASSERT(fp != NULL);
1657 return reinterpret_cast<uword*>(*(fp + kSavedCallerPcSlotFromFp)); 1754 return reinterpret_cast<uword*>(*(fp + kSavedCallerPcSlotFromFp));
1658 } 1755 }
1659 1756
1660 uword* CallerFP(uword* fp) const { 1757 uword* CallerFP(uword* fp) const {
1661 ASSERT(fp != NULL); 1758 ASSERT(fp != NULL);
1662 return reinterpret_cast<uword*>(*(fp + kSavedCallerFpSlotFromFp)); 1759 return reinterpret_cast<uword*>(*(fp + kSavedCallerFpSlotFromFp));
1663 } 1760 }
1664 1761
1762 uword GetCurrentFramePcMarker(uword* fp) {
1763 if (!ValidFramePointer(fp)) {
1764 return 0;
1765 }
1766 return *(fp + kPcMarkerSlotFromFp);
1767 }
1768
1665 bool ValidFramePointer(uword* fp) const { 1769 bool ValidFramePointer(uword* fp) const {
1666 if (fp == NULL) { 1770 if (fp == NULL) {
1667 return false; 1771 return false;
1668 } 1772 }
1669 uword cursor = reinterpret_cast<uword>(fp); 1773 uword cursor = reinterpret_cast<uword>(fp);
1670 cursor += sizeof(fp); 1774 cursor += sizeof(fp);
1671 bool r = cursor >= lower_bound_ && cursor < stack_upper_; 1775 bool r = cursor >= lower_bound_ && cursor < stack_upper_;
1672 return r; 1776 return r;
1673 } 1777 }
1674 1778
1675
1676 Sample* sample_; 1779 Sample* sample_;
1677 const uword stack_upper_; 1780 const uword stack_upper_;
1678 const uword original_pc_; 1781 const uword original_pc_;
1679 const uword original_fp_; 1782 const uword original_fp_;
1680 const uword original_sp_; 1783 const uword original_sp_;
1681 uword lower_bound_; 1784 uword lower_bound_;
1682 }; 1785 };
1683 1786
1684 1787
1685 void Profiler::RecordSampleInterruptCallback( 1788 void Profiler::RecordSampleInterruptCallback(
(...skipping 12 matching lines...) Expand all
1698 return; 1801 return;
1699 } 1802 }
1700 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); 1803 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
1701 if (sample_buffer == NULL) { 1804 if (sample_buffer == NULL) {
1702 return; 1805 return;
1703 } 1806 }
1704 Sample* sample = sample_buffer->ReserveSample(); 1807 Sample* sample = sample_buffer->ReserveSample();
1705 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); 1808 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid);
1706 sample->set_vm_tag(isolate->vm_tag()); 1809 sample->set_vm_tag(isolate->vm_tag());
1707 sample->set_user_tag(isolate->user_tag()); 1810 sample->set_user_tag(isolate->user_tag());
1811 sample->set_sp(state.sp);
1812 sample->set_fp(state.fp);
1708 if (FLAG_profile_native_stack) { 1813 if (FLAG_profile_native_stack) {
1709 // Collect native and Dart frames. 1814 // Collect native and Dart frames.
1710 uword stack_lower = 0; 1815 uword stack_lower = 0;
1711 uword stack_upper = 0; 1816 uword stack_upper = 0;
1712 isolate->GetStackBounds(&stack_lower, &stack_upper); 1817 isolate->GetStackBounds(&stack_lower, &stack_upper);
1713 if ((stack_lower == 0) || (stack_upper == 0)) { 1818 if ((stack_lower == 0) || (stack_upper == 0)) {
1714 stack_lower = 0; 1819 stack_lower = 0;
1715 stack_upper = 0; 1820 stack_upper = 0;
1716 } 1821 }
1717 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper, 1822 ProfilerNativeStackWalker stackWalker(sample, stack_lower, stack_upper,
1718 state.pc, state.fp, state.sp); 1823 state.pc, state.fp, state.sp);
1719 stackWalker.walk(isolate->heap()); 1824 stackWalker.walk(isolate->heap());
1720 } else { 1825 } else {
1721 if ((isolate->top_exit_frame_info() != 0) && 1826 if ((isolate->top_exit_frame_info() != 0) &&
1722 (isolate->stub_code() != NULL)) { 1827 (isolate->stub_code() != NULL)) {
1723 ProfilerDartStackWalker stackWalker(sample); 1828 ProfilerDartStackWalker stackWalker(sample);
1724 stackWalker.walk(); 1829 stackWalker.walk();
1725 } else { 1830 } else {
1726 // TODO(johnmccutchan): Support collecting only Dart frames with 1831 // TODO(johnmccutchan): Support collecting only Dart frames with
1727 // ProfilerNativeStackWalker. 1832 // ProfilerNativeStackWalker.
1728 } 1833 }
1729 } 1834 }
1730 } 1835 }
1731 1836
1732 } // namespace dart 1837 } // namespace dart
OLDNEW
« runtime/vm/profiler.h ('K') | « runtime/vm/profiler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698