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

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

Issue 1274663004: Enable native stack walking for allocation profiling (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 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
« no previous file with comments | « runtime/vm/globals.h ('k') | runtime/vm/tags.h » ('j') | 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/address_sanitizer.h" 5 #include "platform/address_sanitizer.h"
6 #include "platform/memory_sanitizer.h" 6 #include "platform/memory_sanitizer.h"
7 #include "platform/utils.h" 7 #include "platform/utils.h"
8 8
9 #include "vm/allocation.h" 9 #include "vm/allocation.h"
10 #include "vm/atomic.h" 10 #include "vm/atomic.h"
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after
808 new_protect, 808 new_protect,
809 &old_protect); 809 &old_protect);
810 USE(success); 810 USE(success);
811 ASSERT(success); 811 ASSERT(success);
812 ASSERT(old_protect == PAGE_READWRITE); 812 ASSERT(old_protect == PAGE_READWRITE);
813 } 813 }
814 #endif 814 #endif
815 } 815 }
816 816
817 817
818 void Profiler::RecordAllocation(Isolate* isolate, intptr_t cid) { 818 // Is |isolate| executing Dart code?
819 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { 819 static bool ExecutingDart(Isolate* isolate) {
820 // No isolate. 820 ASSERT(isolate != NULL);
821 return; 821 return (isolate->top_exit_frame_info() == 0) &&
822 (isolate->vm_tag() == VMTag::kDartTagId);
823 }
824
825
826 // Has |isolate| exited Dart code?
827 static bool ExitedDart(Isolate* isolate) {
828 return (isolate->top_exit_frame_info() != 0) &&
829 (isolate->vm_tag() != VMTag::kDartTagId);
830 }
831
832
833 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within
834 // it. Return |false| if anything looks suspicious.
835 static bool GetAndValidateIsolateStackBounds(Isolate* isolate,
836 uintptr_t sp,
837 uintptr_t fp,
838 uword* stack_lower,
839 uword* stack_upper) {
840 ASSERT(isolate != NULL);
841 ASSERT(stack_lower != NULL);
842 ASSERT(stack_upper != NULL);
843 #if defined(USING_SIMULATOR)
844 Simulator* simulator = NULL;
845 #endif
846
847 #if defined(USING_SIMULATOR)
848 const bool in_dart_code = ExecutingDart(isolate);
849 if (in_dart_code) {
850 *stack_lower = simulator->StackBase();
851 *stack_upper = simulator->StackTop();
852 } else if (!isolate->GetProfilerStackBounds(stack_lower, stack_upper)) {
853 // Could not get stack boundary.
854 return false;
822 } 855 }
823 ASSERT(isolate != Dart::vm_isolate()); 856 if ((*stack_lower == 0) || (*stack_upper == 0)) {
824 857 return false;
825 const bool exited_dart_code = (isolate->top_exit_frame_info() != 0) && 858 }
826 (isolate->vm_tag() != VMTag::kDartTagId); 859 #else
827 860 if (!isolate->GetProfilerStackBounds(stack_lower, stack_upper) ||
828 if (!exited_dart_code) { 861 (*stack_lower == 0) || (*stack_upper == 0)) {
829 // No Dart frames on stack. 862 // Could not get stack boundary.
830 // TODO(johnmccutchan): Support collecting native stack. 863 return false;
831 return; 864 }
865 #endif
866 if (sp > *stack_lower) {
867 // The stack pointer gives us a tighter lower bound.
868 *stack_lower = sp;
832 } 869 }
833 870
871 if (*stack_lower >= *stack_upper) {
872 // Stack boundary is invalid.
873 return false;
874 }
875
876 if ((sp < *stack_lower) || (sp >= *stack_upper)) {
877 // Stack pointer is outside isolate stack boundary.
878 return false;
879 }
880
881 if ((fp < *stack_lower) || (fp >= *stack_upper)) {
882 // Frame pointer is outside isolate stack boundary.
883 return false;
884 }
885
886 return true;
887 }
888
889
890 // Some simple sanity checking of |pc|, |sp|, and |fp|.
891 static bool InitialRegisterCheck(uintptr_t pc, uintptr_t sp, uintptr_t fp) {
892 if ((sp == 0) || (fp == 0) || (pc == 0)) {
893 // None of these registers should be zero.
894 return false;
895 }
896
897 if (sp > fp) {
898 // Assuming the stack grows down, we should never have a stack pointer above
899 // the frame pointer.
900 return false;
901 }
902
903 return true;
904 }
905
906
907 // Return |isolate|'s sample buffer.
908 static SampleBuffer* GetSampleBuffer(Isolate* isolate) {
834 IsolateProfilerData* profiler_data = isolate->profiler_data(); 909 IsolateProfilerData* profiler_data = isolate->profiler_data();
835 if (profiler_data == NULL) { 910 if (profiler_data == NULL) {
836 // Profiler not initialized. 911 // Profiler not initialized.
837 return; 912 return NULL;
838 } 913 }
914 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
915 return sample_buffer;
916 }
839 917
840 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
841 if (sample_buffer == NULL) {
842 // Profiler not initialized.
843 return;
844 }
845 918
846 const ThreadId thread_id = OSThread::GetCurrentThreadId(); 919 static Sample* SetupSample(Isolate* isolate,
847 // Setup sample. 920 SampleBuffer* sample_buffer,
921 ThreadId tid) {
922 ASSERT(isolate != NULL);
923 ASSERT(sample_buffer != NULL);
848 Sample* sample = sample_buffer->ReserveSample(); 924 Sample* sample = sample_buffer->ReserveSample();
849 sample->Init(isolate, OS::GetCurrentTimeMicros(), thread_id); 925 sample->Init(isolate, OS::GetCurrentTimeMicros(), tid);
850 uword vm_tag = isolate->vm_tag(); 926 uword vm_tag = isolate->vm_tag();
851 #if defined(USING_SIMULATOR) 927 #if defined(USING_SIMULATOR)
852 // When running in the simulator, the runtime entry function address 928 // When running in the simulator, the runtime entry function address
853 // (stored as the vm tag) is the address of a redirect function. 929 // (stored as the vm tag) is the address of a redirect function.
854 // Attempt to find the real runtime entry function address and use that. 930 // Attempt to find the real runtime entry function address and use that.
855 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); 931 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag);
856 if (redirect_vm_tag != 0) { 932 if (redirect_vm_tag != 0) {
857 vm_tag = redirect_vm_tag; 933 vm_tag = redirect_vm_tag;
858 } 934 }
859 #endif 935 #endif
860 sample->set_vm_tag(vm_tag); 936 sample->set_vm_tag(vm_tag);
861 sample->set_user_tag(isolate->user_tag()); 937 sample->set_user_tag(isolate->user_tag());
862 sample->SetAllocationCid(cid); 938 return sample;
863
864 ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, sample);
865 dart_exit_stack_walker.walk();
866 } 939 }
867 940
868 941
942 static bool CheckIsolate(Isolate* isolate) {
943 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
944 // No isolate.
945 return false;
946 }
947 ASSERT(isolate != Dart::vm_isolate());
948 return true;
949 }
950
951
952 #if defined(TARGET_OS_WINDOWS)
953 __declspec(noinline)
954 static uintptr_t GetProgramCounter() {
955 return reinterpret_cast<uintptr_t>(_ReturnAddress());
956 }
957 #else
958 static uintptr_t __attribute__((noinline)) GetProgramCounter() {
959 return reinterpret_cast<uintptr_t>(
960 __builtin_extract_return_addr(__builtin_return_address(0)));
961 }
962 #endif
963
964 void Profiler::RecordAllocation(Isolate* isolate, intptr_t cid) {
965 if (!CheckIsolate(isolate)) {
966 return;
967 }
968
969 const bool exited_dart_code = ExitedDart(isolate);
970
971 if (!exited_dart_code && !FLAG_profile_vm) {
972 // No Dart frames on stack and we are not profiling the vm.
973 return;
974 }
975
976 SampleBuffer* sample_buffer = GetSampleBuffer(isolate);
977 if (sample_buffer == NULL) {
978 // Profiler not initialized.
979 return;
980 }
981
982 if (FLAG_profile_vm) {
983 uintptr_t sp = Isolate::GetCurrentStackPointer();
984 uintptr_t fp = 0;
985 uintptr_t pc = GetProgramCounter();
986
987 COPY_FP_REGISTER(fp);
regis 2015/08/06 16:55:17 I suppose you tell gcc to always generate frame po
988
989 uword stack_lower = 0;
990 uword stack_upper = 0;
991
992 if (!InitialRegisterCheck(pc, sp, fp)) {
993 return;
994 }
995
996 if (!GetAndValidateIsolateStackBounds(isolate,
997 sp,
998 fp,
999 &stack_lower,
1000 &stack_upper)) {
1001 // Could not get stack boundary.
1002 return;
1003 }
1004
1005 Sample* sample = SetupSample(isolate,
1006 sample_buffer,
1007 OSThread::GetCurrentThreadId());
1008 sample->SetAllocationCid(cid);
1009 ProfilerNativeStackWalker native_stack_walker(sample,
1010 stack_lower,
1011 stack_upper,
1012 pc,
1013 fp,
1014 sp);
1015 native_stack_walker.walk();
1016 } else {
1017 ASSERT(exited_dart_code);
1018 Sample* sample = SetupSample(isolate,
1019 sample_buffer,
1020 OSThread::GetCurrentThreadId());
1021 sample->SetAllocationCid(cid);
1022 ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, sample);
1023 dart_exit_stack_walker.walk();
1024 }
1025 }
1026
1027
869 void Profiler::RecordSampleInterruptCallback( 1028 void Profiler::RecordSampleInterruptCallback(
870 const InterruptedThreadState& state, 1029 const InterruptedThreadState& state,
871 void* data) { 1030 void* data) {
872 Isolate* isolate = reinterpret_cast<Isolate*>(data); 1031 Isolate* isolate = reinterpret_cast<Isolate*>(data);
873 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { 1032 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
874 // No isolate. 1033 // No isolate.
875 return; 1034 return;
876 } 1035 }
877
878 ASSERT(isolate != Dart::vm_isolate()); 1036 ASSERT(isolate != Dart::vm_isolate());
879 1037
880 const bool exited_dart_code = (isolate->top_exit_frame_info() != 0) && 1038 SampleBuffer* sample_buffer = GetSampleBuffer(isolate);
881 (isolate->vm_tag() != VMTag::kDartTagId); 1039 if (sample_buffer == NULL) {
882 const bool in_dart_code = (isolate->top_exit_frame_info() == 0) && 1040 // Profiler not initialized.
883 (isolate->vm_tag() == VMTag::kDartTagId); 1041 return;
1042 }
1043
1044 const bool exited_dart_code = ExitedDart(isolate);
1045 const bool in_dart_code = ExecutingDart(isolate);
884 1046
885 uintptr_t sp = 0; 1047 uintptr_t sp = 0;
886 uintptr_t fp = state.fp; 1048 uintptr_t fp = state.fp;
887 uintptr_t pc = state.pc; 1049 uintptr_t pc = state.pc;
888 uintptr_t lr = state.lr;
889 #if defined(USING_SIMULATOR) 1050 #if defined(USING_SIMULATOR)
890 Simulator* simulator = NULL; 1051 Simulator* simulator = NULL;
891 #endif 1052 #endif
892 1053
893 if (in_dart_code) { 1054 if (in_dart_code) {
894 // If we're in Dart code, use the Dart stack pointer. 1055 // If we're in Dart code, use the Dart stack pointer.
895 #if defined(USING_SIMULATOR) 1056 #if defined(USING_SIMULATOR)
896 simulator = isolate->simulator(); 1057 simulator = isolate->simulator();
897 sp = simulator->get_register(SPREG); 1058 sp = simulator->get_register(SPREG);
898 fp = simulator->get_register(FPREG); 1059 fp = simulator->get_register(FPREG);
899 pc = simulator->get_pc(); 1060 pc = simulator->get_pc();
900 lr = simulator->get_register(LRREG);
901 #else 1061 #else
902 sp = state.dsp; 1062 sp = state.dsp;
903 #endif 1063 #endif
904 } else { 1064 } else {
905 // If we're in runtime code, use the C stack pointer. 1065 // If we're in runtime code, use the C stack pointer.
906 sp = state.csp; 1066 sp = state.csp;
907 } 1067 }
908 1068
909 IsolateProfilerData* profiler_data = isolate->profiler_data(); 1069 if (!InitialRegisterCheck(pc, sp, fp)) {
910 if (profiler_data == NULL) {
911 // Profiler not initialized.
912 return; 1070 return;
913 } 1071 }
914 1072
915 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
916 if (sample_buffer == NULL) {
917 // Profiler not initialized.
918 return;
919 }
920
921 if ((sp == 0) || (fp == 0) || (pc == 0)) {
922 // None of these registers should be zero.
923 return;
924 }
925
926 if (sp > fp) {
927 // Assuming the stack grows down, we should never have a stack pointer above
928 // the frame pointer.
929 return;
930 }
931
932 if (StubCode::InJumpToExceptionHandlerStub(pc)) { 1073 if (StubCode::InJumpToExceptionHandlerStub(pc)) {
933 // The JumpToExceptionHandler stub manually adjusts the stack pointer, 1074 // The JumpToExceptionHandler stub manually adjusts the stack pointer,
934 // frame pointer, and some isolate state before jumping to a catch entry. 1075 // frame pointer, and some isolate state before jumping to a catch entry.
935 // It is not safe to walk the stack when executing this stub. 1076 // It is not safe to walk the stack when executing this stub.
936 return; 1077 return;
937 } 1078 }
938 1079
939 uword stack_lower = 0; 1080 uword stack_lower = 0;
940 uword stack_upper = 0; 1081 uword stack_upper = 0;
941 #if defined(USING_SIMULATOR) 1082 if (!GetAndValidateIsolateStackBounds(isolate,
942 if (in_dart_code) { 1083 sp,
943 stack_lower = simulator->StackBase(); 1084 fp,
944 stack_upper = simulator->StackTop(); 1085 &stack_lower,
945 } else if (!isolate->GetProfilerStackBounds(&stack_lower, &stack_upper)) { 1086 &stack_upper)) {
946 // Could not get stack boundary. 1087 // Could not get stack boundary.
947 return; 1088 return;
948 } 1089 }
949 if ((stack_lower == 0) || (stack_upper == 0)) {
950 return;
951 }
952 #else
953 if (!isolate->GetProfilerStackBounds(&stack_lower, &stack_upper) ||
954 (stack_lower == 0) || (stack_upper == 0)) {
955 // Could not get stack boundary.
956 return;
957 }
958 #endif
959
960 if (sp > stack_lower) {
961 // The stack pointer gives us a tighter lower bound.
962 stack_lower = sp;
963 }
964
965 if (stack_lower >= stack_upper) {
966 // Stack boundary is invalid.
967 return;
968 }
969
970 if ((sp < stack_lower) || (sp >= stack_upper)) {
971 // Stack pointer is outside isolate stack boundary.
972 return;
973 }
974
975 if ((fp < stack_lower) || (fp >= stack_upper)) {
976 // Frame pointer is outside isolate stack boundary.
977 return;
978 }
979 1090
980 // At this point we have a valid stack boundary for this isolate and 1091 // At this point we have a valid stack boundary for this isolate and
981 // know that our initial stack and frame pointers are within the boundary. 1092 // know that our initial stack and frame pointers are within the boundary.
982 1093
983 // Setup sample. 1094 // Setup sample.
984 Sample* sample = sample_buffer->ReserveSample(); 1095 Sample* sample = SetupSample(isolate,
985 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); 1096 sample_buffer,
986 uword vm_tag = isolate->vm_tag(); 1097 OSThread::GetCurrentThreadId());
987 #if defined(USING_SIMULATOR)
988 // When running in the simulator, the runtime entry function address
989 // (stored as the vm tag) is the address of a redirect function.
990 // Attempt to find the real runtime entry function address and use that.
991 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag);
992 if (redirect_vm_tag != 0) {
993 vm_tag = redirect_vm_tag;
994 }
995 #endif
996 // Increment counter for vm tag. 1098 // Increment counter for vm tag.
997 VMTagCounters* counters = isolate->vm_tag_counters(); 1099 VMTagCounters* counters = isolate->vm_tag_counters();
998 ASSERT(counters != NULL); 1100 ASSERT(counters != NULL);
999 counters->Increment(vm_tag); 1101 counters->Increment(sample->vm_tag());
1000 sample->set_vm_tag(vm_tag);
1001 sample->set_user_tag(isolate->user_tag());
1002 sample->set_lr(lr);
1003 1102
1004 ProfilerNativeStackWalker native_stack_walker(sample, 1103 ProfilerNativeStackWalker native_stack_walker(sample,
1005 stack_lower, 1104 stack_lower,
1006 stack_upper, 1105 stack_upper,
1007 pc, 1106 pc,
1008 fp, 1107 fp,
1009 sp); 1108 sp);
1010 1109
1011 ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, sample); 1110 ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, sample);
1012 1111
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 uword pc) { 1322 uword pc) {
1224 return vm_isolate->heap()->CodeContains(pc) 1323 return vm_isolate->heap()->CodeContains(pc)
1225 || isolate->heap()->CodeContains(pc); 1324 || isolate->heap()->CodeContains(pc);
1226 } 1325 }
1227 1326
1228 1327
1229 ProcessedSampleBuffer::ProcessedSampleBuffer() { 1328 ProcessedSampleBuffer::ProcessedSampleBuffer() {
1230 } 1329 }
1231 1330
1232 } // namespace dart 1331 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/globals.h ('k') | runtime/vm/tags.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698