Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 "vm/profiler_service.h" | 5 #include "vm/profiler_service.h" |
| 6 | 6 |
| 7 #include "vm/growable_array.h" | 7 #include "vm/growable_array.h" |
| 8 #include "vm/hash_map.h" | 8 #include "vm/hash_map.h" |
| 9 #include "vm/log.h" | 9 #include "vm/log.h" |
| 10 #include "vm/malloc_hooks.h" | 10 #include "vm/malloc_hooks.h" |
| (...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1210 kOptimized, | 1210 kOptimized, |
| 1211 kUnoptimized, | 1211 kUnoptimized, |
| 1212 kNative, | 1212 kNative, |
| 1213 kInlineStart, | 1213 kInlineStart, |
| 1214 kInlineFinish, | 1214 kInlineFinish, |
| 1215 kNumProfileInfoKind, | 1215 kNumProfileInfoKind, |
| 1216 }; | 1216 }; |
| 1217 | 1217 |
| 1218 ProfileBuilder(Thread* thread, | 1218 ProfileBuilder(Thread* thread, |
| 1219 SampleFilter* filter, | 1219 SampleFilter* filter, |
| 1220 SampleBuffer* sample_buffer, | |
| 1220 Profile::TagOrder tag_order, | 1221 Profile::TagOrder tag_order, |
| 1221 intptr_t extra_tags, | 1222 intptr_t extra_tags, |
| 1222 Profile* profile) | 1223 Profile* profile) |
| 1223 : thread_(thread), | 1224 : thread_(thread), |
| 1224 vm_isolate_(Dart::vm_isolate()), | 1225 vm_isolate_(Dart::vm_isolate()), |
| 1225 filter_(filter), | 1226 filter_(filter), |
| 1227 sample_buffer_(sample_buffer), | |
| 1226 tag_order_(tag_order), | 1228 tag_order_(tag_order), |
| 1227 extra_tags_(extra_tags), | 1229 extra_tags_(extra_tags), |
| 1228 profile_(profile), | 1230 profile_(profile), |
| 1229 deoptimized_code_(new DeoptimizedCodeSet(thread->isolate())), | 1231 deoptimized_code_(new DeoptimizedCodeSet(thread->isolate())), |
| 1230 null_code_(Code::ZoneHandle()), | 1232 null_code_(Code::ZoneHandle()), |
| 1231 null_function_(Function::ZoneHandle()), | 1233 null_function_(Function::ZoneHandle()), |
| 1232 tick_functions_(false), | 1234 tick_functions_(false), |
| 1233 inclusive_tree_(false), | 1235 inclusive_tree_(false), |
| 1234 samples_(NULL), | 1236 samples_(NULL), |
| 1235 info_kind_(kNone) { | 1237 info_kind_(kNone) { |
| 1238 ASSERT((sample_buffer_ == Profiler::sample_buffer()) || | |
| 1239 (sample_buffer_ == Profiler::allocation_sample_buffer())); | |
| 1236 ASSERT(profile_ != NULL); | 1240 ASSERT(profile_ != NULL); |
| 1237 } | 1241 } |
| 1238 | 1242 |
| 1239 void Build() { | 1243 void Build() { |
| 1240 ScopeTimer sw("ProfileBuilder::Build", FLAG_trace_profiler); | 1244 ScopeTimer sw("ProfileBuilder::Build", FLAG_trace_profiler); |
| 1241 if (!FilterSamples()) { | 1245 if (!FilterSamples()) { |
| 1242 return; | 1246 return; |
| 1243 } | 1247 } |
| 1244 | 1248 |
| 1245 Setup(); | 1249 Setup(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1277 RegisterProfileCodeTag(VMTag::kNoneCodeTagId); | 1281 RegisterProfileCodeTag(VMTag::kNoneCodeTagId); |
| 1278 RegisterProfileCodeTag(VMTag::kOptimizedCodeTagId); | 1282 RegisterProfileCodeTag(VMTag::kOptimizedCodeTagId); |
| 1279 RegisterProfileCodeTag(VMTag::kUnoptimizedCodeTagId); | 1283 RegisterProfileCodeTag(VMTag::kUnoptimizedCodeTagId); |
| 1280 RegisterProfileCodeTag(VMTag::kNativeCodeTagId); | 1284 RegisterProfileCodeTag(VMTag::kNativeCodeTagId); |
| 1281 RegisterProfileCodeTag(VMTag::kInlineStartCodeTagId); | 1285 RegisterProfileCodeTag(VMTag::kInlineStartCodeTagId); |
| 1282 RegisterProfileCodeTag(VMTag::kInlineEndCodeTagId); | 1286 RegisterProfileCodeTag(VMTag::kInlineEndCodeTagId); |
| 1283 } | 1287 } |
| 1284 | 1288 |
| 1285 bool FilterSamples() { | 1289 bool FilterSamples() { |
| 1286 ScopeTimer sw("ProfileBuilder::FilterSamples", FLAG_trace_profiler); | 1290 ScopeTimer sw("ProfileBuilder::FilterSamples", FLAG_trace_profiler); |
| 1287 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | 1291 samples_ = sample_buffer_->BuildProcessedSampleBuffer(filter_); |
|
zra
2017/06/30 18:49:17
Retain the NULL check, or ASSERT non-null.
bkonyi
2017/07/05 18:20:52
Done.
| |
| 1288 if (sample_buffer == NULL) { | |
| 1289 return false; | |
| 1290 } | |
| 1291 samples_ = sample_buffer->BuildProcessedSampleBuffer(filter_); | |
| 1292 profile_->samples_ = samples_; | 1292 profile_->samples_ = samples_; |
| 1293 profile_->sample_count_ = samples_->length(); | 1293 profile_->sample_count_ = samples_->length(); |
| 1294 return true; | 1294 return true; |
| 1295 } | 1295 } |
| 1296 | 1296 |
| 1297 void UpdateMinMaxTimes(int64_t timestamp) { | 1297 void UpdateMinMaxTimes(int64_t timestamp) { |
| 1298 profile_->min_time_ = | 1298 profile_->min_time_ = |
| 1299 timestamp < profile_->min_time_ ? timestamp : profile_->min_time_; | 1299 timestamp < profile_->min_time_ ? timestamp : profile_->min_time_; |
| 1300 profile_->max_time_ = | 1300 profile_->max_time_ = |
| 1301 timestamp > profile_->max_time_ ? timestamp : profile_->max_time_; | 1301 timestamp > profile_->max_time_ ? timestamp : profile_->max_time_; |
| (...skipping 1021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2323 (tag_order_ == Profile::kVMUser) || (tag_order_ == Profile::kVM); | 2323 (tag_order_ == Profile::kVMUser) || (tag_order_ == Profile::kVM); |
| 2324 } | 2324 } |
| 2325 | 2325 |
| 2326 bool TagsEnabled(intptr_t extra_tags_bits) const { | 2326 bool TagsEnabled(intptr_t extra_tags_bits) const { |
| 2327 return (extra_tags_ & extra_tags_bits) != 0; | 2327 return (extra_tags_ & extra_tags_bits) != 0; |
| 2328 } | 2328 } |
| 2329 | 2329 |
| 2330 Thread* thread_; | 2330 Thread* thread_; |
| 2331 Isolate* vm_isolate_; | 2331 Isolate* vm_isolate_; |
| 2332 SampleFilter* filter_; | 2332 SampleFilter* filter_; |
| 2333 SampleBuffer* sample_buffer_; | |
| 2333 Profile::TagOrder tag_order_; | 2334 Profile::TagOrder tag_order_; |
| 2334 intptr_t extra_tags_; | 2335 intptr_t extra_tags_; |
| 2335 Profile* profile_; | 2336 Profile* profile_; |
| 2336 DeoptimizedCodeSet* deoptimized_code_; | 2337 DeoptimizedCodeSet* deoptimized_code_; |
| 2337 const Code& null_code_; | 2338 const Code& null_code_; |
| 2338 const Function& null_function_; | 2339 const Function& null_function_; |
| 2339 bool tick_functions_; | 2340 bool tick_functions_; |
| 2340 bool inclusive_tree_; | 2341 bool inclusive_tree_; |
| 2341 ProfileCodeInlinedFunctionsCache inlined_functions_cache_; | 2342 ProfileCodeInlinedFunctionsCache inlined_functions_cache_; |
| 2342 ProcessedSampleBuffer* samples_; | 2343 ProcessedSampleBuffer* samples_; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2358 max_time_(0) { | 2359 max_time_(0) { |
| 2359 ASSERT(isolate_ != NULL); | 2360 ASSERT(isolate_ != NULL); |
| 2360 for (intptr_t i = 0; i < kNumTrieKinds; i++) { | 2361 for (intptr_t i = 0; i < kNumTrieKinds; i++) { |
| 2361 roots_[i] = NULL; | 2362 roots_[i] = NULL; |
| 2362 } | 2363 } |
| 2363 } | 2364 } |
| 2364 | 2365 |
| 2365 | 2366 |
| 2366 void Profile::Build(Thread* thread, | 2367 void Profile::Build(Thread* thread, |
| 2367 SampleFilter* filter, | 2368 SampleFilter* filter, |
| 2369 SampleBuffer* sample_buffer, | |
| 2368 TagOrder tag_order, | 2370 TagOrder tag_order, |
| 2369 intptr_t extra_tags) { | 2371 intptr_t extra_tags) { |
| 2370 ProfileBuilder builder(thread, filter, tag_order, extra_tags, this); | 2372 ProfileBuilder builder(thread, filter, sample_buffer, tag_order, extra_tags, |
| 2373 this); | |
| 2371 builder.Build(); | 2374 builder.Build(); |
| 2372 } | 2375 } |
| 2373 | 2376 |
| 2374 | 2377 |
| 2375 intptr_t Profile::NumFunctions() const { | 2378 intptr_t Profile::NumFunctions() const { |
| 2376 return functions_->length(); | 2379 return functions_->length(); |
| 2377 } | 2380 } |
| 2378 | 2381 |
| 2379 ProfileFunction* Profile::GetFunction(intptr_t index) { | 2382 ProfileFunction* Profile::GetFunction(intptr_t index) { |
| 2380 ASSERT(functions_ != NULL); | 2383 ASSERT(functions_ != NULL); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2741 ASSERT(parent_ != NULL); | 2744 ASSERT(parent_ != NULL); |
| 2742 return parent_->NumChildren(); | 2745 return parent_->NumChildren(); |
| 2743 } | 2746 } |
| 2744 | 2747 |
| 2745 | 2748 |
| 2746 void ProfilerService::PrintJSONImpl(Thread* thread, | 2749 void ProfilerService::PrintJSONImpl(Thread* thread, |
| 2747 JSONStream* stream, | 2750 JSONStream* stream, |
| 2748 Profile::TagOrder tag_order, | 2751 Profile::TagOrder tag_order, |
| 2749 intptr_t extra_tags, | 2752 intptr_t extra_tags, |
| 2750 SampleFilter* filter, | 2753 SampleFilter* filter, |
| 2754 SampleBuffer* sample_buffer, | |
| 2751 bool as_timeline) { | 2755 bool as_timeline) { |
| 2752 Isolate* isolate = thread->isolate(); | 2756 Isolate* isolate = thread->isolate(); |
| 2753 // Disable thread interrupts while processing the buffer. | 2757 // Disable thread interrupts while processing the buffer. |
| 2754 DisableThreadInterruptsScope dtis(thread); | 2758 DisableThreadInterruptsScope dtis(thread); |
| 2755 | 2759 |
| 2756 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | |
| 2757 if (sample_buffer == NULL) { | 2760 if (sample_buffer == NULL) { |
| 2758 stream->PrintError(kFeatureDisabled, NULL); | 2761 stream->PrintError(kFeatureDisabled, NULL); |
| 2759 return; | 2762 return; |
| 2760 } | 2763 } |
| 2761 | 2764 |
| 2762 { | 2765 { |
| 2763 StackZone zone(thread); | 2766 StackZone zone(thread); |
| 2764 HANDLESCOPE(thread); | 2767 HANDLESCOPE(thread); |
| 2765 Profile profile(isolate); | 2768 Profile profile(isolate); |
| 2766 profile.Build(thread, filter, tag_order, extra_tags); | 2769 profile.Build(thread, filter, sample_buffer, tag_order, extra_tags); |
| 2767 if (as_timeline) { | 2770 if (as_timeline) { |
| 2768 profile.PrintTimelineJSON(stream); | 2771 profile.PrintTimelineJSON(stream); |
| 2769 } else { | 2772 } else { |
| 2770 profile.PrintProfileJSON(stream); | 2773 profile.PrintProfileJSON(stream); |
| 2771 } | 2774 } |
| 2772 } | 2775 } |
| 2773 } | 2776 } |
| 2774 | 2777 |
| 2775 | 2778 |
| 2776 class NoAllocationSampleFilter : public SampleFilter { | 2779 class NoAllocationSampleFilter : public SampleFilter { |
| 2777 public: | 2780 public: |
| 2778 NoAllocationSampleFilter(Dart_Port port, | 2781 NoAllocationSampleFilter(Dart_Port port, |
| 2779 intptr_t thread_task_mask, | 2782 intptr_t thread_task_mask, |
| 2780 int64_t time_origin_micros, | 2783 int64_t time_origin_micros, |
| 2781 int64_t time_extent_micros) | 2784 int64_t time_extent_micros) |
| 2782 : SampleFilter(port, | 2785 : SampleFilter(port, |
| 2783 thread_task_mask, | 2786 thread_task_mask, |
| 2784 time_origin_micros, | 2787 time_origin_micros, |
| 2785 time_extent_micros) {} | 2788 time_extent_micros) {} |
| 2786 | 2789 |
| 2787 bool FilterSample(Sample* sample) { | 2790 bool FilterSample(Sample* sample) { return !sample->is_allocation_sample(); } |
| 2788 return !sample->is_allocation_sample() && | |
| 2789 !sample->is_native_allocation_sample(); | |
| 2790 } | |
| 2791 }; | 2791 }; |
| 2792 | 2792 |
| 2793 | 2793 |
| 2794 void ProfilerService::PrintJSON(JSONStream* stream, | 2794 void ProfilerService::PrintJSON(JSONStream* stream, |
| 2795 Profile::TagOrder tag_order, | 2795 Profile::TagOrder tag_order, |
| 2796 intptr_t extra_tags, | 2796 intptr_t extra_tags, |
| 2797 int64_t time_origin_micros, | 2797 int64_t time_origin_micros, |
| 2798 int64_t time_extent_micros) { | 2798 int64_t time_extent_micros) { |
| 2799 Thread* thread = Thread::Current(); | 2799 Thread* thread = Thread::Current(); |
| 2800 Isolate* isolate = thread->isolate(); | 2800 Isolate* isolate = thread->isolate(); |
| 2801 NoAllocationSampleFilter filter(isolate->main_port(), Thread::kMutatorTask, | 2801 NoAllocationSampleFilter filter(isolate->main_port(), Thread::kMutatorTask, |
| 2802 time_origin_micros, time_extent_micros); | 2802 time_origin_micros, time_extent_micros); |
| 2803 const bool as_timeline = false; | 2803 const bool as_timeline = false; |
| 2804 PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter, as_timeline); | 2804 PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter, |
| 2805 Profiler::sample_buffer(), as_timeline); | |
| 2805 } | 2806 } |
| 2806 | 2807 |
| 2807 | 2808 |
| 2808 class ClassAllocationSampleFilter : public SampleFilter { | 2809 class ClassAllocationSampleFilter : public SampleFilter { |
| 2809 public: | 2810 public: |
| 2810 ClassAllocationSampleFilter(Dart_Port port, | 2811 ClassAllocationSampleFilter(Dart_Port port, |
| 2811 const Class& cls, | 2812 const Class& cls, |
| 2812 intptr_t thread_task_mask, | 2813 intptr_t thread_task_mask, |
| 2813 int64_t time_origin_micros, | 2814 int64_t time_origin_micros, |
| 2814 int64_t time_extent_micros) | 2815 int64_t time_extent_micros) |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 2834 Profile::TagOrder tag_order, | 2835 Profile::TagOrder tag_order, |
| 2835 const Class& cls, | 2836 const Class& cls, |
| 2836 int64_t time_origin_micros, | 2837 int64_t time_origin_micros, |
| 2837 int64_t time_extent_micros) { | 2838 int64_t time_extent_micros) { |
| 2838 Thread* thread = Thread::Current(); | 2839 Thread* thread = Thread::Current(); |
| 2839 Isolate* isolate = thread->isolate(); | 2840 Isolate* isolate = thread->isolate(); |
| 2840 ClassAllocationSampleFilter filter(isolate->main_port(), cls, | 2841 ClassAllocationSampleFilter filter(isolate->main_port(), cls, |
| 2841 Thread::kMutatorTask, time_origin_micros, | 2842 Thread::kMutatorTask, time_origin_micros, |
| 2842 time_extent_micros); | 2843 time_extent_micros); |
| 2843 const bool as_timeline = false; | 2844 const bool as_timeline = false; |
| 2844 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); | 2845 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, |
| 2846 Profiler::sample_buffer(), as_timeline); | |
| 2845 } | 2847 } |
| 2846 | 2848 |
| 2847 | 2849 |
| 2848 void ProfilerService::PrintNativeAllocationJSON(JSONStream* stream, | 2850 void ProfilerService::PrintNativeAllocationJSON(JSONStream* stream, |
| 2849 Profile::TagOrder tag_order, | 2851 Profile::TagOrder tag_order, |
| 2850 int64_t time_origin_micros, | 2852 int64_t time_origin_micros, |
| 2851 int64_t time_extent_micros) { | 2853 int64_t time_extent_micros) { |
| 2852 Thread* thread = Thread::Current(); | 2854 Thread* thread = Thread::Current(); |
| 2853 NativeAllocationSampleFilter filter(time_origin_micros, time_extent_micros); | 2855 NativeAllocationSampleFilter filter(time_origin_micros, time_extent_micros); |
| 2854 const bool as_timeline = false; | 2856 const bool as_timeline = false; |
| 2855 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); | 2857 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, |
| 2858 Profiler::allocation_sample_buffer(), as_timeline); | |
| 2856 } | 2859 } |
| 2857 | 2860 |
| 2858 | 2861 |
| 2859 void ProfilerService::PrintTimelineJSON(JSONStream* stream, | 2862 void ProfilerService::PrintTimelineJSON(JSONStream* stream, |
| 2860 Profile::TagOrder tag_order, | 2863 Profile::TagOrder tag_order, |
| 2861 int64_t time_origin_micros, | 2864 int64_t time_origin_micros, |
| 2862 int64_t time_extent_micros) { | 2865 int64_t time_extent_micros) { |
| 2863 Thread* thread = Thread::Current(); | 2866 Thread* thread = Thread::Current(); |
| 2864 Isolate* isolate = thread->isolate(); | 2867 Isolate* isolate = thread->isolate(); |
| 2865 const intptr_t thread_task_mask = Thread::kMutatorTask | | 2868 const intptr_t thread_task_mask = Thread::kMutatorTask | |
| 2866 Thread::kCompilerTask | | 2869 Thread::kCompilerTask | |
| 2867 Thread::kSweeperTask | Thread::kMarkerTask; | 2870 Thread::kSweeperTask | Thread::kMarkerTask; |
| 2868 NoAllocationSampleFilter filter(isolate->main_port(), thread_task_mask, | 2871 NoAllocationSampleFilter filter(isolate->main_port(), thread_task_mask, |
| 2869 time_origin_micros, time_extent_micros); | 2872 time_origin_micros, time_extent_micros); |
| 2870 const bool as_timeline = true; | 2873 const bool as_timeline = true; |
| 2871 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); | 2874 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, |
| 2875 Profiler::sample_buffer(), as_timeline); | |
| 2872 } | 2876 } |
| 2873 | 2877 |
| 2874 | 2878 |
| 2875 void ProfilerService::ClearSamples() { | 2879 void ProfilerService::ClearSamples() { |
| 2876 SampleBuffer* sample_buffer = Profiler::sample_buffer(); | 2880 SampleBuffer* sample_buffer = Profiler::sample_buffer(); |
| 2877 if (sample_buffer == NULL) { | 2881 if (sample_buffer == NULL) { |
| 2878 return; | 2882 return; |
| 2879 } | 2883 } |
| 2880 | 2884 |
| 2881 Thread* thread = Thread::Current(); | 2885 Thread* thread = Thread::Current(); |
| 2882 Isolate* isolate = thread->isolate(); | 2886 Isolate* isolate = thread->isolate(); |
| 2883 | 2887 |
| 2884 // Disable thread interrupts while processing the buffer. | 2888 // Disable thread interrupts while processing the buffer. |
| 2885 DisableThreadInterruptsScope dtis(thread); | 2889 DisableThreadInterruptsScope dtis(thread); |
| 2886 | 2890 |
| 2887 ClearProfileVisitor clear_profile(isolate); | 2891 ClearProfileVisitor clear_profile(isolate); |
| 2888 sample_buffer->VisitSamples(&clear_profile); | 2892 sample_buffer->VisitSamples(&clear_profile); |
| 2889 } | 2893 } |
| 2890 | 2894 |
| 2891 #endif // !PRODUCT | 2895 #endif // !PRODUCT |
| 2892 | 2896 |
| 2893 } // namespace dart | 2897 } // namespace dart |
| OLD | NEW |