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

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
« runtime/vm/globals.h ('K') | « runtime/vm/globals.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/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 = 0;
984 uintptr_t fp = 0;
985 uintptr_t pc = GetProgramCounter();
986
987 COPY_SP_REGISTER(sp);
988 COPY_FP_REGISTER(fp);
989
990 uword stack_lower = 0;
991 uword stack_upper = 0;
992
993 if (!InitialRegisterCheck(pc, sp, fp)) {
994 return;
995 }
996
997 if (!GetAndValidateIsolateStackBounds(isolate,
998 sp,
999 fp,
1000 &stack_lower,
1001 &stack_upper)) {
1002 // Could not get stack boundary.
1003 return;
1004 }
1005
1006 Sample* sample = SetupSample(isolate,
1007 sample_buffer,
1008 OSThread::GetCurrentThreadId());
1009 sample->SetAllocationCid(cid);
1010 ProfilerNativeStackWalker native_stack_walker(sample,
1011 stack_lower,
1012 stack_upper,
1013 pc,
1014 fp,
1015 sp);
1016 native_stack_walker.walk();
1017 } else {
1018 ASSERT(exited_dart_code);
1019 Sample* sample = SetupSample(isolate,
1020 sample_buffer,
1021 OSThread::GetCurrentThreadId());
1022 sample->SetAllocationCid(cid);
1023 ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, sample);
1024 dart_exit_stack_walker.walk();
1025 }
1026 }
1027
1028
869 void Profiler::RecordSampleInterruptCallback( 1029 void Profiler::RecordSampleInterruptCallback(
870 const InterruptedThreadState& state, 1030 const InterruptedThreadState& state,
871 void* data) { 1031 void* data) {
872 Isolate* isolate = reinterpret_cast<Isolate*>(data); 1032 Isolate* isolate = reinterpret_cast<Isolate*>(data);
873 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { 1033 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
874 // No isolate. 1034 // No isolate.
875 return; 1035 return;
876 } 1036 }
877
878 ASSERT(isolate != Dart::vm_isolate()); 1037 ASSERT(isolate != Dart::vm_isolate());
879 1038
880 const bool exited_dart_code = (isolate->top_exit_frame_info() != 0) && 1039 SampleBuffer* sample_buffer = GetSampleBuffer(isolate);
881 (isolate->vm_tag() != VMTag::kDartTagId); 1040 if (sample_buffer == NULL) {
882 const bool in_dart_code = (isolate->top_exit_frame_info() == 0) && 1041 // Profiler not initialized.
883 (isolate->vm_tag() == VMTag::kDartTagId); 1042 return;
1043 }
1044
1045 const bool exited_dart_code = ExitedDart(isolate);
1046 const bool in_dart_code = ExecutingDart(isolate);
884 1047
885 uintptr_t sp = 0; 1048 uintptr_t sp = 0;
886 uintptr_t fp = state.fp; 1049 uintptr_t fp = state.fp;
887 uintptr_t pc = state.pc; 1050 uintptr_t pc = state.pc;
888 uintptr_t lr = state.lr;
889 #if defined(USING_SIMULATOR) 1051 #if defined(USING_SIMULATOR)
890 Simulator* simulator = NULL; 1052 Simulator* simulator = NULL;
891 #endif 1053 #endif
892 1054
893 if (in_dart_code) { 1055 if (in_dart_code) {
894 // If we're in Dart code, use the Dart stack pointer. 1056 // If we're in Dart code, use the Dart stack pointer.
895 #if defined(USING_SIMULATOR) 1057 #if defined(USING_SIMULATOR)
896 simulator = isolate->simulator(); 1058 simulator = isolate->simulator();
897 sp = simulator->get_register(SPREG); 1059 sp = simulator->get_register(SPREG);
898 fp = simulator->get_register(FPREG); 1060 fp = simulator->get_register(FPREG);
899 pc = simulator->get_pc(); 1061 pc = simulator->get_pc();
900 lr = simulator->get_register(LRREG);
901 #else 1062 #else
902 sp = state.dsp; 1063 sp = state.dsp;
903 #endif 1064 #endif
904 } else { 1065 } else {
905 // If we're in runtime code, use the C stack pointer. 1066 // If we're in runtime code, use the C stack pointer.
906 sp = state.csp; 1067 sp = state.csp;
907 } 1068 }
908 1069
909 IsolateProfilerData* profiler_data = isolate->profiler_data(); 1070 if (!InitialRegisterCheck(pc, sp, fp)) {
910 if (profiler_data == NULL) {
911 // Profiler not initialized.
912 return; 1071 return;
913 } 1072 }
914 1073
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)) { 1074 if (StubCode::InJumpToExceptionHandlerStub(pc)) {
933 // The JumpToExceptionHandler stub manually adjusts the stack pointer, 1075 // The JumpToExceptionHandler stub manually adjusts the stack pointer,
934 // frame pointer, and some isolate state before jumping to a catch entry. 1076 // 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. 1077 // It is not safe to walk the stack when executing this stub.
936 return; 1078 return;
937 } 1079 }
938 1080
939 uword stack_lower = 0; 1081 uword stack_lower = 0;
940 uword stack_upper = 0; 1082 uword stack_upper = 0;
941 #if defined(USING_SIMULATOR) 1083 if (!GetAndValidateIsolateStackBounds(isolate,
942 if (in_dart_code) { 1084 sp,
943 stack_lower = simulator->StackBase(); 1085 fp,
944 stack_upper = simulator->StackTop(); 1086 &stack_lower,
945 } else if (!isolate->GetProfilerStackBounds(&stack_lower, &stack_upper)) { 1087 &stack_upper)) {
946 // Could not get stack boundary. 1088 // Could not get stack boundary.
947 return; 1089 return;
948 } 1090 }
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 1091
980 // At this point we have a valid stack boundary for this isolate and 1092 // 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. 1093 // know that our initial stack and frame pointers are within the boundary.
982 1094
983 // Setup sample. 1095 // Setup sample.
984 Sample* sample = sample_buffer->ReserveSample(); 1096 Sample* sample = SetupSample(isolate,
985 sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid); 1097 sample_buffer,
986 uword vm_tag = isolate->vm_tag(); 1098 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. 1099 // Increment counter for vm tag.
997 VMTagCounters* counters = isolate->vm_tag_counters(); 1100 VMTagCounters* counters = isolate->vm_tag_counters();
998 ASSERT(counters != NULL); 1101 ASSERT(counters != NULL);
999 counters->Increment(vm_tag); 1102 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 1103
1004 ProfilerNativeStackWalker native_stack_walker(sample, 1104 ProfilerNativeStackWalker native_stack_walker(sample,
1005 stack_lower, 1105 stack_lower,
1006 stack_upper, 1106 stack_upper,
1007 pc, 1107 pc,
1008 fp, 1108 fp,
1009 sp); 1109 sp);
1010 1110
1011 ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, sample); 1111 ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, sample);
1012 1112
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 uword pc) { 1323 uword pc) {
1224 return vm_isolate->heap()->CodeContains(pc) 1324 return vm_isolate->heap()->CodeContains(pc)
1225 || isolate->heap()->CodeContains(pc); 1325 || isolate->heap()->CodeContains(pc);
1226 } 1326 }
1227 1327
1228 1328
1229 ProcessedSampleBuffer::ProcessedSampleBuffer() { 1329 ProcessedSampleBuffer::ProcessedSampleBuffer() {
1230 } 1330 }
1231 1331
1232 } // namespace dart 1332 } // namespace dart
OLDNEW
« runtime/vm/globals.h ('K') | « runtime/vm/globals.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698