| OLD | NEW |
| 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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 } | 158 } |
| 159 if (!FLAG_profile) { | 159 if (!FLAG_profile) { |
| 160 return; | 160 return; |
| 161 } | 161 } |
| 162 ASSERT(initialized_); | 162 ASSERT(initialized_); |
| 163 IsolateProfilerData* profiler_data = isolate->profiler_data(); | 163 IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| 164 if (profiler_data == NULL) { | 164 if (profiler_data == NULL) { |
| 165 return; | 165 return; |
| 166 } | 166 } |
| 167 Thread* thread = Thread::Current(); | 167 Thread* thread = Thread::Current(); |
| 168 thread->SetThreadInterrupter(RecordSampleInterruptCallback, isolate); | 168 thread->SetThreadInterrupter(RecordSampleInterruptCallback, thread); |
| 169 ThreadInterrupter::WakeUp(); | 169 ThreadInterrupter::WakeUp(); |
| 170 } | 170 } |
| 171 | 171 |
| 172 | 172 |
| 173 void Profiler::EndExecution(Isolate* isolate) { | 173 void Profiler::EndExecution(Isolate* isolate) { |
| 174 if (isolate == NULL) { | 174 if (isolate == NULL) { |
| 175 return; | 175 return; |
| 176 } | 176 } |
| 177 if (!FLAG_profile) { | 177 if (!FLAG_profile) { |
| 178 return; | 178 return; |
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 new_protect, | 843 new_protect, |
| 844 &old_protect); | 844 &old_protect); |
| 845 USE(success); | 845 USE(success); |
| 846 ASSERT(success); | 846 ASSERT(success); |
| 847 ASSERT(old_protect == PAGE_READWRITE); | 847 ASSERT(old_protect == PAGE_READWRITE); |
| 848 } | 848 } |
| 849 #endif | 849 #endif |
| 850 } | 850 } |
| 851 | 851 |
| 852 | 852 |
| 853 // Is |isolate| executing Dart code? | 853 // Is |thread| executing Dart code? |
| 854 static bool ExecutingDart(Isolate* isolate) { | 854 static bool ExecutingDart(Thread* thread) { |
| 855 ASSERT(isolate != NULL); | 855 ASSERT(thread != NULL); |
| 856 return (isolate->top_exit_frame_info() == 0) && | 856 return (thread->top_exit_frame_info() == 0) && |
| 857 (isolate->vm_tag() == VMTag::kDartTagId); | 857 (thread->vm_tag() == VMTag::kDartTagId); |
| 858 } | 858 } |
| 859 | 859 |
| 860 | 860 |
| 861 // Has |isolate| exited Dart code? | 861 // Has |thread| exited Dart code? |
| 862 static bool ExitedDart(Isolate* isolate) { | 862 static bool ExitedDart(Thread* thread) { |
| 863 return (isolate->top_exit_frame_info() != 0) && | 863 return (thread->top_exit_frame_info() != 0) && |
| 864 (isolate->vm_tag() != VMTag::kDartTagId); | 864 (thread->vm_tag() != VMTag::kDartTagId); |
| 865 } | 865 } |
| 866 | 866 |
| 867 | 867 |
| 868 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within | 868 // Get |isolate|'s stack boundary and verify that |sp| and |fp| are within |
| 869 // it. Return |false| if anything looks suspicious. | 869 // it. Return |false| if anything looks suspicious. |
| 870 static bool GetAndValidateIsolateStackBounds(Isolate* isolate, | 870 static bool GetAndValidateIsolateStackBounds(Thread* thread, |
| 871 uintptr_t sp, | 871 uintptr_t sp, |
| 872 uintptr_t fp, | 872 uintptr_t fp, |
| 873 uword* stack_lower, | 873 uword* stack_lower, |
| 874 uword* stack_upper) { | 874 uword* stack_upper) { |
| 875 ASSERT(thread != NULL); |
| 876 Isolate* isolate = thread->isolate(); |
| 875 ASSERT(isolate != NULL); | 877 ASSERT(isolate != NULL); |
| 876 ASSERT(stack_lower != NULL); | 878 ASSERT(stack_lower != NULL); |
| 877 ASSERT(stack_upper != NULL); | 879 ASSERT(stack_upper != NULL); |
| 878 #if defined(USING_SIMULATOR) | 880 #if defined(USING_SIMULATOR) |
| 879 const bool in_dart_code = ExecutingDart(isolate); | 881 const bool in_dart_code = ExecutingDart(thread); |
| 880 if (in_dart_code) { | 882 if (in_dart_code) { |
| 881 Simulator* simulator = isolate->simulator(); | 883 Simulator* simulator = isolate->simulator(); |
| 882 *stack_lower = simulator->StackBase(); | 884 *stack_lower = simulator->StackBase(); |
| 883 *stack_upper = simulator->StackTop(); | 885 *stack_upper = simulator->StackTop(); |
| 884 } else if (!isolate->GetProfilerStackBounds(stack_lower, stack_upper)) { | 886 } else if (!isolate->GetProfilerStackBounds(stack_lower, stack_upper)) { |
| 885 // Could not get stack boundary. | 887 // Could not get stack boundary. |
| 886 return false; | 888 return false; |
| 887 } | 889 } |
| 888 if ((*stack_lower == 0) || (*stack_upper == 0)) { | 890 if ((*stack_lower == 0) || (*stack_upper == 0)) { |
| 889 return false; | 891 return false; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 941 IsolateProfilerData* profiler_data = isolate->profiler_data(); | 943 IsolateProfilerData* profiler_data = isolate->profiler_data(); |
| 942 if (profiler_data == NULL) { | 944 if (profiler_data == NULL) { |
| 943 // Profiler not initialized. | 945 // Profiler not initialized. |
| 944 return NULL; | 946 return NULL; |
| 945 } | 947 } |
| 946 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); | 948 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); |
| 947 return sample_buffer; | 949 return sample_buffer; |
| 948 } | 950 } |
| 949 | 951 |
| 950 | 952 |
| 951 static Sample* SetupSample(Isolate* isolate, | 953 static Sample* SetupSample(Thread* thread, |
| 952 SampleBuffer* sample_buffer, | 954 SampleBuffer* sample_buffer, |
| 953 ThreadId tid) { | 955 ThreadId tid) { |
| 954 ASSERT(isolate != NULL); | 956 ASSERT(thread != NULL); |
| 957 Isolate* isolate = thread->isolate(); |
| 955 ASSERT(sample_buffer != NULL); | 958 ASSERT(sample_buffer != NULL); |
| 956 Sample* sample = sample_buffer->ReserveSample(); | 959 Sample* sample = sample_buffer->ReserveSample(); |
| 957 sample->Init(isolate, OS::GetCurrentTimeMicros(), tid); | 960 sample->Init(isolate, OS::GetCurrentTimeMicros(), tid); |
| 958 uword vm_tag = isolate->vm_tag(); | 961 uword vm_tag = thread->vm_tag(); |
| 959 #if defined(USING_SIMULATOR) | 962 #if defined(USING_SIMULATOR) |
| 960 // When running in the simulator, the runtime entry function address | 963 // When running in the simulator, the runtime entry function address |
| 961 // (stored as the vm tag) is the address of a redirect function. | 964 // (stored as the vm tag) is the address of a redirect function. |
| 962 // Attempt to find the real runtime entry function address and use that. | 965 // Attempt to find the real runtime entry function address and use that. |
| 963 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); | 966 uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag); |
| 964 if (redirect_vm_tag != 0) { | 967 if (redirect_vm_tag != 0) { |
| 965 vm_tag = redirect_vm_tag; | 968 vm_tag = redirect_vm_tag; |
| 966 } | 969 } |
| 967 #endif | 970 #endif |
| 968 sample->set_vm_tag(vm_tag); | 971 sample->set_vm_tag(vm_tag); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 986 static uintptr_t GetProgramCounter() { | 989 static uintptr_t GetProgramCounter() { |
| 987 return reinterpret_cast<uintptr_t>(_ReturnAddress()); | 990 return reinterpret_cast<uintptr_t>(_ReturnAddress()); |
| 988 } | 991 } |
| 989 #else | 992 #else |
| 990 static uintptr_t __attribute__((noinline)) GetProgramCounter() { | 993 static uintptr_t __attribute__((noinline)) GetProgramCounter() { |
| 991 return reinterpret_cast<uintptr_t>( | 994 return reinterpret_cast<uintptr_t>( |
| 992 __builtin_extract_return_addr(__builtin_return_address(0))); | 995 __builtin_extract_return_addr(__builtin_return_address(0))); |
| 993 } | 996 } |
| 994 #endif | 997 #endif |
| 995 | 998 |
| 996 void Profiler::RecordAllocation(Isolate* isolate, intptr_t cid) { | 999 void Profiler::RecordAllocation(Thread* thread, intptr_t cid) { |
| 1000 ASSERT(thread != NULL); |
| 1001 Isolate* isolate = thread->isolate(); |
| 997 if (!CheckIsolate(isolate)) { | 1002 if (!CheckIsolate(isolate)) { |
| 998 return; | 1003 return; |
| 999 } | 1004 } |
| 1000 | 1005 |
| 1001 const bool exited_dart_code = ExitedDart(isolate); | 1006 const bool exited_dart_code = ExitedDart(thread); |
| 1002 | 1007 |
| 1003 SampleBuffer* sample_buffer = GetSampleBuffer(isolate); | 1008 SampleBuffer* sample_buffer = GetSampleBuffer(isolate); |
| 1004 if (sample_buffer == NULL) { | 1009 if (sample_buffer == NULL) { |
| 1005 // Profiler not initialized. | 1010 // Profiler not initialized. |
| 1006 return; | 1011 return; |
| 1007 } | 1012 } |
| 1008 | 1013 |
| 1009 if (FLAG_profile_vm) { | 1014 if (FLAG_profile_vm) { |
| 1010 uintptr_t sp = Isolate::GetCurrentStackPointer(); | 1015 uintptr_t sp = Isolate::GetCurrentStackPointer(); |
| 1011 uintptr_t fp = 0; | 1016 uintptr_t fp = 0; |
| 1012 uintptr_t pc = GetProgramCounter(); | 1017 uintptr_t pc = GetProgramCounter(); |
| 1013 | 1018 |
| 1014 COPY_FP_REGISTER(fp); | 1019 COPY_FP_REGISTER(fp); |
| 1015 | 1020 |
| 1016 uword stack_lower = 0; | 1021 uword stack_lower = 0; |
| 1017 uword stack_upper = 0; | 1022 uword stack_upper = 0; |
| 1018 | 1023 |
| 1019 if (!InitialRegisterCheck(pc, sp, fp)) { | 1024 if (!InitialRegisterCheck(pc, sp, fp)) { |
| 1020 return; | 1025 return; |
| 1021 } | 1026 } |
| 1022 | 1027 |
| 1023 if (!GetAndValidateIsolateStackBounds(isolate, | 1028 if (!GetAndValidateIsolateStackBounds(thread, |
| 1024 sp, | 1029 sp, |
| 1025 fp, | 1030 fp, |
| 1026 &stack_lower, | 1031 &stack_lower, |
| 1027 &stack_upper)) { | 1032 &stack_upper)) { |
| 1028 // Could not get stack boundary. | 1033 // Could not get stack boundary. |
| 1029 return; | 1034 return; |
| 1030 } | 1035 } |
| 1031 | 1036 |
| 1032 Sample* sample = SetupSample(isolate, | 1037 Sample* sample = SetupSample(thread, |
| 1033 sample_buffer, | 1038 sample_buffer, |
| 1034 OSThread::GetCurrentThreadId()); | 1039 OSThread::GetCurrentThreadId()); |
| 1035 sample->SetAllocationCid(cid); | 1040 sample->SetAllocationCid(cid); |
| 1036 ProfilerNativeStackWalker native_stack_walker(isolate, | 1041 ProfilerNativeStackWalker native_stack_walker(isolate, |
| 1037 sample, | 1042 sample, |
| 1038 sample_buffer, | 1043 sample_buffer, |
| 1039 stack_lower, | 1044 stack_lower, |
| 1040 stack_upper, | 1045 stack_upper, |
| 1041 pc, | 1046 pc, |
| 1042 fp, | 1047 fp, |
| 1043 sp); | 1048 sp); |
| 1044 native_stack_walker.walk(); | 1049 native_stack_walker.walk(); |
| 1045 } else if (exited_dart_code) { | 1050 } else if (exited_dart_code) { |
| 1046 Sample* sample = SetupSample(isolate, | 1051 Sample* sample = SetupSample(thread, |
| 1047 sample_buffer, | 1052 sample_buffer, |
| 1048 OSThread::GetCurrentThreadId()); | 1053 OSThread::GetCurrentThreadId()); |
| 1049 sample->SetAllocationCid(cid); | 1054 sample->SetAllocationCid(cid); |
| 1050 ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, | 1055 ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, |
| 1051 sample, | 1056 sample, |
| 1052 sample_buffer); | 1057 sample_buffer); |
| 1053 dart_exit_stack_walker.walk(); | 1058 dart_exit_stack_walker.walk(); |
| 1054 } else { | 1059 } else { |
| 1055 // Fall back. | 1060 // Fall back. |
| 1056 uintptr_t pc = GetProgramCounter(); | 1061 uintptr_t pc = GetProgramCounter(); |
| 1057 Sample* sample = SetupSample(isolate, | 1062 Sample* sample = SetupSample(thread, |
| 1058 sample_buffer, | 1063 sample_buffer, |
| 1059 OSThread::GetCurrentThreadId()); | 1064 OSThread::GetCurrentThreadId()); |
| 1060 sample->SetAllocationCid(cid); | 1065 sample->SetAllocationCid(cid); |
| 1061 sample->set_vm_tag(VMTag::kEmbedderTagId); | 1066 sample->set_vm_tag(VMTag::kEmbedderTagId); |
| 1062 sample->SetAt(0, pc); | 1067 sample->SetAt(0, pc); |
| 1063 } | 1068 } |
| 1064 } | 1069 } |
| 1065 | 1070 |
| 1066 | 1071 |
| 1067 void Profiler::RecordSampleInterruptCallback( | 1072 void Profiler::RecordSampleInterruptCallback( |
| 1068 const InterruptedThreadState& state, | 1073 const InterruptedThreadState& state, |
| 1069 void* data) { | 1074 void* data) { |
| 1070 Isolate* isolate = reinterpret_cast<Isolate*>(data); | 1075 Thread* thread = reinterpret_cast<Thread*>(data); |
| 1076 Isolate* isolate = thread->isolate(); |
| 1071 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { | 1077 if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) { |
| 1072 // No isolate. | 1078 // No isolate. |
| 1073 return; | 1079 return; |
| 1074 } | 1080 } |
| 1075 ASSERT(isolate != Dart::vm_isolate()); | 1081 ASSERT(isolate != Dart::vm_isolate()); |
| 1076 | 1082 |
| 1077 SampleBuffer* sample_buffer = GetSampleBuffer(isolate); | 1083 SampleBuffer* sample_buffer = GetSampleBuffer(isolate); |
| 1078 if (sample_buffer == NULL) { | 1084 if (sample_buffer == NULL) { |
| 1079 // Profiler not initialized. | 1085 // Profiler not initialized. |
| 1080 return; | 1086 return; |
| 1081 } | 1087 } |
| 1082 | 1088 |
| 1083 const bool exited_dart_code = ExitedDart(isolate); | 1089 const bool exited_dart_code = ExitedDart(thread); |
| 1084 const bool in_dart_code = ExecutingDart(isolate); | 1090 const bool in_dart_code = ExecutingDart(thread); |
| 1085 | 1091 |
| 1086 uintptr_t sp = 0; | 1092 uintptr_t sp = 0; |
| 1087 uintptr_t fp = state.fp; | 1093 uintptr_t fp = state.fp; |
| 1088 uintptr_t pc = state.pc; | 1094 uintptr_t pc = state.pc; |
| 1089 #if defined(USING_SIMULATOR) | 1095 #if defined(USING_SIMULATOR) |
| 1090 Simulator* simulator = NULL; | 1096 Simulator* simulator = NULL; |
| 1091 #endif | 1097 #endif |
| 1092 | 1098 |
| 1093 if (in_dart_code) { | 1099 if (in_dart_code) { |
| 1094 // If we're in Dart code, use the Dart stack pointer. | 1100 // If we're in Dart code, use the Dart stack pointer. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1111 | 1117 |
| 1112 if (StubCode::InJumpToExceptionHandlerStub(pc)) { | 1118 if (StubCode::InJumpToExceptionHandlerStub(pc)) { |
| 1113 // The JumpToExceptionHandler stub manually adjusts the stack pointer, | 1119 // The JumpToExceptionHandler stub manually adjusts the stack pointer, |
| 1114 // frame pointer, and some isolate state before jumping to a catch entry. | 1120 // frame pointer, and some isolate state before jumping to a catch entry. |
| 1115 // It is not safe to walk the stack when executing this stub. | 1121 // It is not safe to walk the stack when executing this stub. |
| 1116 return; | 1122 return; |
| 1117 } | 1123 } |
| 1118 | 1124 |
| 1119 uword stack_lower = 0; | 1125 uword stack_lower = 0; |
| 1120 uword stack_upper = 0; | 1126 uword stack_upper = 0; |
| 1121 if (!GetAndValidateIsolateStackBounds(isolate, | 1127 if (!GetAndValidateIsolateStackBounds(thread, |
| 1122 sp, | 1128 sp, |
| 1123 fp, | 1129 fp, |
| 1124 &stack_lower, | 1130 &stack_lower, |
| 1125 &stack_upper)) { | 1131 &stack_upper)) { |
| 1126 // Could not get stack boundary. | 1132 // Could not get stack boundary. |
| 1127 return; | 1133 return; |
| 1128 } | 1134 } |
| 1129 | 1135 |
| 1130 // At this point we have a valid stack boundary for this isolate and | 1136 // At this point we have a valid stack boundary for this isolate and |
| 1131 // know that our initial stack and frame pointers are within the boundary. | 1137 // know that our initial stack and frame pointers are within the boundary. |
| 1132 | 1138 |
| 1133 // Setup sample. | 1139 // Setup sample. |
| 1134 Sample* sample = SetupSample(isolate, | 1140 Sample* sample = SetupSample(thread, |
| 1135 sample_buffer, | 1141 sample_buffer, |
| 1136 OSThread::GetCurrentThreadId()); | 1142 OSThread::GetCurrentThreadId()); |
| 1137 // Increment counter for vm tag. | 1143 // Increment counter for vm tag. |
| 1138 VMTagCounters* counters = isolate->vm_tag_counters(); | 1144 VMTagCounters* counters = isolate->vm_tag_counters(); |
| 1139 ASSERT(counters != NULL); | 1145 ASSERT(counters != NULL); |
| 1140 counters->Increment(sample->vm_tag()); | 1146 counters->Increment(sample->vm_tag()); |
| 1141 | 1147 |
| 1142 ProfilerNativeStackWalker native_stack_walker(isolate, | 1148 ProfilerNativeStackWalker native_stack_walker(isolate, |
| 1143 sample, | 1149 sample, |
| 1144 sample_buffer, | 1150 sample_buffer, |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1385 uword pc) { | 1391 uword pc) { |
| 1386 return vm_isolate->heap()->CodeContains(pc) | 1392 return vm_isolate->heap()->CodeContains(pc) |
| 1387 || isolate->heap()->CodeContains(pc); | 1393 || isolate->heap()->CodeContains(pc); |
| 1388 } | 1394 } |
| 1389 | 1395 |
| 1390 | 1396 |
| 1391 ProcessedSampleBuffer::ProcessedSampleBuffer() { | 1397 ProcessedSampleBuffer::ProcessedSampleBuffer() { |
| 1392 } | 1398 } |
| 1393 | 1399 |
| 1394 } // namespace dart | 1400 } // namespace dart |
| OLD | NEW |