OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/trace_event/memory_dump_manager.h" | 5 #include "base/trace_event/memory_dump_manager.h" |
6 | 6 |
7 #include <inttypes.h> | 7 #include <inttypes.h> |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 10 matching lines...) Expand all Loading... | |
21 #include "base/debug/thread_heap_usage_tracker.h" | 21 #include "base/debug/thread_heap_usage_tracker.h" |
22 #include "base/memory/ptr_util.h" | 22 #include "base/memory/ptr_util.h" |
23 #include "base/optional.h" | 23 #include "base/optional.h" |
24 #include "base/strings/pattern.h" | 24 #include "base/strings/pattern.h" |
25 #include "base/strings/string_piece.h" | 25 #include "base/strings/string_piece.h" |
26 #include "base/threading/thread.h" | 26 #include "base/threading/thread.h" |
27 #include "base/threading/thread_task_runner_handle.h" | 27 #include "base/threading/thread_task_runner_handle.h" |
28 #include "base/trace_event/heap_profiler.h" | 28 #include "base/trace_event/heap_profiler.h" |
29 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" | 29 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" |
30 #include "base/trace_event/heap_profiler_event_filter.h" | 30 #include "base/trace_event/heap_profiler_event_filter.h" |
31 #include "base/trace_event/heap_profiler_serialization_state.h" | |
31 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" | 32 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" |
32 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" | 33 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" |
33 #include "base/trace_event/malloc_dump_provider.h" | 34 #include "base/trace_event/malloc_dump_provider.h" |
34 #include "base/trace_event/memory_dump_provider.h" | 35 #include "base/trace_event/memory_dump_provider.h" |
35 #include "base/trace_event/memory_dump_scheduler.h" | 36 #include "base/trace_event/memory_dump_scheduler.h" |
36 #include "base/trace_event/memory_dump_session_state.h" | |
37 #include "base/trace_event/memory_infra_background_whitelist.h" | 37 #include "base/trace_event/memory_infra_background_whitelist.h" |
38 #include "base/trace_event/memory_peak_detector.h" | 38 #include "base/trace_event/memory_peak_detector.h" |
39 #include "base/trace_event/memory_tracing_observer.h" | 39 #include "base/trace_event/memory_tracing_observer.h" |
40 #include "base/trace_event/process_memory_dump.h" | 40 #include "base/trace_event/process_memory_dump.h" |
41 #include "base/trace_event/trace_event.h" | 41 #include "base/trace_event/trace_event.h" |
42 #include "base/trace_event/trace_event_argument.h" | 42 #include "base/trace_event/trace_event_argument.h" |
43 #include "build/build_config.h" | 43 #include "build/build_config.h" |
44 | 44 |
45 #if defined(OS_ANDROID) | 45 #if defined(OS_ANDROID) |
46 #include "base/trace_event/java_heap_dump_provider_android.h" | 46 #include "base/trace_event/java_heap_dump_provider_android.h" |
(...skipping 29 matching lines...) Expand all Loading... | |
76 const ProcessMemoryDump* pmd, | 76 const ProcessMemoryDump* pmd, |
77 MemoryDumpCallbackResult::OSMemDump* osDump) { | 77 MemoryDumpCallbackResult::OSMemDump* osDump) { |
78 if (pmd->has_process_totals()) { | 78 if (pmd->has_process_totals()) { |
79 const ProcessMemoryTotals* totals = pmd->process_totals(); | 79 const ProcessMemoryTotals* totals = pmd->process_totals(); |
80 osDump->resident_set_kb = totals->resident_set_bytes() / 1024; | 80 osDump->resident_set_kb = totals->resident_set_bytes() / 1024; |
81 osDump->platform_private_footprint = totals->GetPlatformPrivateFootprint(); | 81 osDump->platform_private_footprint = totals->GetPlatformPrivateFootprint(); |
82 } | 82 } |
83 } | 83 } |
84 | 84 |
85 // Proxy class which wraps a ConvertableToTraceFormat owned by the | 85 // Proxy class which wraps a ConvertableToTraceFormat owned by the |
86 // |session_state| into a proxy object that can be added to the trace event log. | 86 // |heap_profiler_serialization_state| into a proxy object that can be added to |
87 // This is to solve the problem that the MemoryDumpSessionState is refcounted | 87 // the trace event log. This is to solve the problem that the |
88 // but the tracing subsystem wants a std::unique_ptr<ConvertableToTraceFormat>. | 88 // HeapProfilerSerializationState is refcounted but the tracing subsystem wants |
89 // a std::unique_ptr<ConvertableToTraceFormat>. | |
89 template <typename T> | 90 template <typename T> |
90 struct SessionStateConvertableProxy : public ConvertableToTraceFormat { | 91 struct SessionStateConvertableProxy : public ConvertableToTraceFormat { |
91 using GetterFunctPtr = T* (MemoryDumpSessionState::*)() const; | 92 using GetterFunctPtr = T* (HeapProfilerSerializationState::*)() const; |
92 | 93 |
93 SessionStateConvertableProxy( | 94 SessionStateConvertableProxy(scoped_refptr<HeapProfilerSerializationState> |
94 scoped_refptr<MemoryDumpSessionState> session_state, | 95 heap_profiler_serialization_state, |
95 GetterFunctPtr getter_function) | 96 GetterFunctPtr getter_function) |
96 : session_state(session_state), getter_function(getter_function) {} | 97 : heap_profiler_serialization_state(heap_profiler_serialization_state), |
98 getter_function(getter_function) {} | |
97 | 99 |
98 void AppendAsTraceFormat(std::string* out) const override { | 100 void AppendAsTraceFormat(std::string* out) const override { |
99 return (session_state.get()->*getter_function)()->AppendAsTraceFormat(out); | 101 return (heap_profiler_serialization_state.get()->*getter_function)() |
102 ->AppendAsTraceFormat(out); | |
100 } | 103 } |
101 | 104 |
102 void EstimateTraceMemoryOverhead( | 105 void EstimateTraceMemoryOverhead( |
103 TraceEventMemoryOverhead* overhead) override { | 106 TraceEventMemoryOverhead* overhead) override { |
104 return (session_state.get()->*getter_function)() | 107 return (heap_profiler_serialization_state.get()->*getter_function)() |
105 ->EstimateTraceMemoryOverhead(overhead); | 108 ->EstimateTraceMemoryOverhead(overhead); |
106 } | 109 } |
107 | 110 |
108 scoped_refptr<MemoryDumpSessionState> session_state; | 111 scoped_refptr<HeapProfilerSerializationState> |
112 heap_profiler_serialization_state; | |
109 GetterFunctPtr const getter_function; | 113 GetterFunctPtr const getter_function; |
110 }; | 114 }; |
111 | 115 |
112 void OnPeakDetected(MemoryDumpLevelOfDetail level_of_detail) { | 116 void OnPeakDetected(MemoryDumpLevelOfDetail level_of_detail) { |
113 MemoryDumpManager::GetInstance()->RequestGlobalDump( | 117 MemoryDumpManager::GetInstance()->RequestGlobalDump( |
114 MemoryDumpType::PEAK_MEMORY_USAGE, level_of_detail); | 118 MemoryDumpType::PEAK_MEMORY_USAGE, level_of_detail); |
115 } | 119 } |
116 | 120 |
117 void OnPeriodicSchedulerTick(MemoryDumpLevelOfDetail level_of_detail) { | 121 void OnPeriodicSchedulerTick(MemoryDumpLevelOfDetail level_of_detail) { |
118 MemoryDumpManager::GetInstance()->RequestGlobalDump( | 122 MemoryDumpManager::GetInstance()->RequestGlobalDump( |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
400 (*mdp_iter)->disabled = true; | 404 (*mdp_iter)->disabled = true; |
401 dump_providers_.erase(mdp_iter); | 405 dump_providers_.erase(mdp_iter); |
402 } | 406 } |
403 | 407 |
404 void MemoryDumpManager::RequestGlobalDump( | 408 void MemoryDumpManager::RequestGlobalDump( |
405 MemoryDumpType dump_type, | 409 MemoryDumpType dump_type, |
406 MemoryDumpLevelOfDetail level_of_detail, | 410 MemoryDumpLevelOfDetail level_of_detail, |
407 const GlobalMemoryDumpCallback& callback) { | 411 const GlobalMemoryDumpCallback& callback) { |
408 // Bail out immediately if tracing is not enabled at all or if the dump mode | 412 // Bail out immediately if tracing is not enabled at all or if the dump mode |
409 // is not allowed. | 413 // is not allowed. |
410 if (!UNLIKELY(subtle::NoBarrier_Load(&is_enabled_)) || | 414 if (!UNLIKELY(subtle::NoBarrier_Load(&is_enabled_))) { |
411 !IsDumpModeAllowed(level_of_detail)) { | |
ssid
2017/05/05 18:18:33
Hm , if we remove this check and also remove is_en
| |
412 VLOG(1) << kLogPrefix << " failed because " << kTraceCategory | 415 VLOG(1) << kLogPrefix << " failed because " << kTraceCategory |
413 << " tracing category is not enabled or the requested dump mode is " | 416 << " tracing category is not enabled."; |
414 "not allowed by trace config."; | |
415 if (!callback.is_null()) | 417 if (!callback.is_null()) |
416 callback.Run(0u /* guid */, false /* success */); | 418 callback.Run(0u /* guid */, false /* success */); |
417 return; | 419 return; |
418 } | 420 } |
419 | 421 |
420 const uint64_t guid = | 422 const uint64_t guid = |
421 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); | 423 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); |
422 | 424 |
423 // Creates an async event to keep track of the global dump evolution. | 425 // Creates an async event to keep track of the global dump evolution. |
424 // The |wrapped_callback| will generate the ASYNC_END event and then invoke | 426 // The |wrapped_callback| will generate the ASYNC_END event and then invoke |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
493 ->GetCurrentTraceConfig() | 495 ->GetCurrentTraceConfig() |
494 .IsArgumentFilterEnabled()) { | 496 .IsArgumentFilterEnabled()) { |
495 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); | 497 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); |
496 } | 498 } |
497 | 499 |
498 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; | 500 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; |
499 { | 501 { |
500 AutoLock lock(lock_); | 502 AutoLock lock(lock_); |
501 | 503 |
502 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( | 504 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( |
503 args, dump_providers_, session_state_, callback, | 505 args, dump_providers_, heap_profiler_serialization_state_, callback, |
504 GetOrCreateBgTaskRunnerLocked())); | 506 GetOrCreateBgTaskRunnerLocked())); |
505 | 507 |
506 // Safety check to prevent reaching here without calling RequestGlobalDump, | |
507 // with disallowed modes. If |session_state_| is null then tracing is | |
508 // disabled. | |
509 CHECK(!session_state_ || | |
510 session_state_->IsDumpModeAllowed(args.level_of_detail)); | |
511 | |
512 // If enabled, holds back the peak detector resetting its estimation window. | 508 // If enabled, holds back the peak detector resetting its estimation window. |
513 MemoryPeakDetector::GetInstance()->Throttle(); | 509 MemoryPeakDetector::GetInstance()->Throttle(); |
514 } | 510 } |
515 | 511 |
516 // Start the process dump. This involves task runner hops as specified by the | 512 // Start the process dump. This involves task runner hops as specified by the |
517 // MemoryDumpProvider(s) in RegisterDumpProvider()). | 513 // MemoryDumpProvider(s) in RegisterDumpProvider()). |
518 SetupNextMemoryDump(std::move(pmd_async_state)); | 514 SetupNextMemoryDump(std::move(pmd_async_state)); |
519 } | 515 } |
520 | 516 |
521 // PostTask InvokeOnMemoryDump() to the dump provider's sequenced task runner. A | 517 // PostTask InvokeOnMemoryDump() to the dump provider's sequenced task runner. A |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
768 pmd_async_state->callback.Run(dump_guid, dump_successful, result); | 764 pmd_async_state->callback.Run(dump_guid, dump_successful, result); |
769 pmd_async_state->callback.Reset(); | 765 pmd_async_state->callback.Reset(); |
770 } | 766 } |
771 | 767 |
772 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", | 768 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", |
773 TRACE_ID_LOCAL(dump_guid)); | 769 TRACE_ID_LOCAL(dump_guid)); |
774 } | 770 } |
775 | 771 |
776 void MemoryDumpManager::Enable( | 772 void MemoryDumpManager::Enable( |
777 const TraceConfig::MemoryDumpConfig& memory_dump_config) { | 773 const TraceConfig::MemoryDumpConfig& memory_dump_config) { |
778 | 774 scoped_refptr<HeapProfilerSerializationState> |
779 scoped_refptr<MemoryDumpSessionState> session_state = | 775 heap_profiler_serialization_state = new HeapProfilerSerializationState; |
780 new MemoryDumpSessionState; | 776 heap_profiler_serialization_state |
781 session_state->SetAllowedDumpModes(memory_dump_config.allowed_dump_modes); | 777 ->set_heap_profiler_breakdown_threshold_bytes( |
782 session_state->set_heap_profiler_breakdown_threshold_bytes( | 778 memory_dump_config.heap_profiler_options.breakdown_threshold_bytes); |
783 memory_dump_config.heap_profiler_options.breakdown_threshold_bytes); | |
784 if (heap_profiling_enabled_) { | 779 if (heap_profiling_enabled_) { |
785 // If heap profiling is enabled, the stack frame deduplicator and type name | 780 // If heap profiling is enabled, the stack frame deduplicator and type name |
786 // deduplicator will be in use. Add a metadata events to write the frames | 781 // deduplicator will be in use. Add a metadata events to write the frames |
787 // and type IDs. | 782 // and type IDs. |
788 session_state->SetStackFrameDeduplicator( | 783 heap_profiler_serialization_state->SetStackFrameDeduplicator( |
789 WrapUnique(new StackFrameDeduplicator)); | 784 WrapUnique(new StackFrameDeduplicator)); |
790 | 785 |
791 session_state->SetTypeNameDeduplicator( | 786 heap_profiler_serialization_state->SetTypeNameDeduplicator( |
792 WrapUnique(new TypeNameDeduplicator)); | 787 WrapUnique(new TypeNameDeduplicator)); |
793 | 788 |
794 TRACE_EVENT_API_ADD_METADATA_EVENT( | 789 TRACE_EVENT_API_ADD_METADATA_EVENT( |
795 TraceLog::GetCategoryGroupEnabled("__metadata"), "stackFrames", | 790 TraceLog::GetCategoryGroupEnabled("__metadata"), "stackFrames", |
796 "stackFrames", | 791 "stackFrames", |
797 MakeUnique<SessionStateConvertableProxy<StackFrameDeduplicator>>( | 792 MakeUnique<SessionStateConvertableProxy<StackFrameDeduplicator>>( |
798 session_state, &MemoryDumpSessionState::stack_frame_deduplicator)); | 793 heap_profiler_serialization_state, |
794 &HeapProfilerSerializationState::stack_frame_deduplicator)); | |
799 | 795 |
800 TRACE_EVENT_API_ADD_METADATA_EVENT( | 796 TRACE_EVENT_API_ADD_METADATA_EVENT( |
801 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", | 797 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", |
802 "typeNames", | 798 "typeNames", |
803 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( | 799 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( |
804 session_state, &MemoryDumpSessionState::type_name_deduplicator)); | 800 heap_profiler_serialization_state, |
801 &HeapProfilerSerializationState::type_name_deduplicator)); | |
805 } | 802 } |
806 | 803 |
807 AutoLock lock(lock_); | 804 AutoLock lock(lock_); |
808 | 805 |
809 // At this point we must have the ability to request global dumps. | 806 // At this point we must have the ability to request global dumps. |
810 DCHECK(!request_dump_function_.is_null()); | 807 DCHECK(!request_dump_function_.is_null()); |
811 session_state_ = session_state; | 808 heap_profiler_serialization_state_ = heap_profiler_serialization_state; |
812 | 809 |
813 subtle::NoBarrier_Store(&is_enabled_, 1); | 810 subtle::NoBarrier_Store(&is_enabled_, 1); |
814 | 811 |
815 MemoryDumpScheduler::Config periodic_config; | 812 MemoryDumpScheduler::Config periodic_config; |
816 bool peak_detector_configured = false; | 813 bool peak_detector_configured = false; |
817 for (const auto& trigger : memory_dump_config.triggers) { | 814 for (const auto& trigger : memory_dump_config.triggers) { |
818 if (!session_state_->IsDumpModeAllowed(trigger.level_of_detail)) { | |
819 NOTREACHED(); | |
820 continue; | |
821 } | |
822 if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { | 815 if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { |
823 if (periodic_config.triggers.empty()) { | 816 if (periodic_config.triggers.empty()) { |
824 periodic_config.callback = BindRepeating(&OnPeriodicSchedulerTick); | 817 periodic_config.callback = BindRepeating(&OnPeriodicSchedulerTick); |
825 } | 818 } |
826 periodic_config.triggers.push_back( | 819 periodic_config.triggers.push_back( |
827 {trigger.level_of_detail, trigger.min_time_between_dumps_ms}); | 820 {trigger.level_of_detail, trigger.min_time_between_dumps_ms}); |
828 } else if (trigger.trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) { | 821 } else if (trigger.trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) { |
829 // At most one peak trigger is allowed. | 822 // At most one peak trigger is allowed. |
830 CHECK(!peak_detector_configured); | 823 CHECK(!peak_detector_configured); |
831 peak_detector_configured = true; | 824 peak_detector_configured = true; |
(...skipping 30 matching lines...) Expand all Loading... | |
862 // There might be a memory dump in progress while this happens. Therefore, | 855 // There might be a memory dump in progress while this happens. Therefore, |
863 // ensure that the MDM state which depends on the tracing enabled / disabled | 856 // ensure that the MDM state which depends on the tracing enabled / disabled |
864 // state is always accessed by the dumping methods holding the |lock_|. | 857 // state is always accessed by the dumping methods holding the |lock_|. |
865 if (!subtle::NoBarrier_Load(&is_enabled_)) | 858 if (!subtle::NoBarrier_Load(&is_enabled_)) |
866 return; | 859 return; |
867 subtle::NoBarrier_Store(&is_enabled_, 0); | 860 subtle::NoBarrier_Store(&is_enabled_, 0); |
868 { | 861 { |
869 AutoLock lock(lock_); | 862 AutoLock lock(lock_); |
870 MemoryDumpScheduler::GetInstance()->Stop(); | 863 MemoryDumpScheduler::GetInstance()->Stop(); |
871 MemoryPeakDetector::GetInstance()->TearDown(); | 864 MemoryPeakDetector::GetInstance()->TearDown(); |
872 session_state_ = nullptr; | 865 heap_profiler_serialization_state_ = nullptr; |
873 } | 866 } |
874 } | 867 } |
875 | 868 |
876 bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) { | |
877 AutoLock lock(lock_); | |
878 if (!session_state_) | |
879 return false; | |
880 return session_state_->IsDumpModeAllowed(dump_mode); | |
881 } | |
882 | |
883 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( | 869 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( |
884 MemoryDumpRequestArgs req_args, | 870 MemoryDumpRequestArgs req_args, |
885 const MemoryDumpProviderInfo::OrderedSet& dump_providers, | 871 const MemoryDumpProviderInfo::OrderedSet& dump_providers, |
886 scoped_refptr<MemoryDumpSessionState> session_state, | 872 scoped_refptr<HeapProfilerSerializationState> |
873 heap_profiler_serialization_state, | |
887 ProcessMemoryDumpCallback callback, | 874 ProcessMemoryDumpCallback callback, |
888 scoped_refptr<SequencedTaskRunner> dump_thread_task_runner) | 875 scoped_refptr<SequencedTaskRunner> dump_thread_task_runner) |
889 : req_args(req_args), | 876 : req_args(req_args), |
890 session_state(std::move(session_state)), | 877 heap_profiler_serialization_state( |
878 std::move(heap_profiler_serialization_state)), | |
891 callback(callback), | 879 callback(callback), |
892 dump_successful(true), | 880 dump_successful(true), |
893 callback_task_runner(ThreadTaskRunnerHandle::Get()), | 881 callback_task_runner(ThreadTaskRunnerHandle::Get()), |
894 dump_thread_task_runner(std::move(dump_thread_task_runner)) { | 882 dump_thread_task_runner(std::move(dump_thread_task_runner)) { |
895 pending_dump_providers.reserve(dump_providers.size()); | 883 pending_dump_providers.reserve(dump_providers.size()); |
896 pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend()); | 884 pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend()); |
897 } | 885 } |
898 | 886 |
899 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { | 887 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { |
900 } | 888 } |
901 | 889 |
902 ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState:: | 890 ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState:: |
903 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid, | 891 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid, |
904 const MemoryDumpArgs& dump_args) { | 892 const MemoryDumpArgs& dump_args) { |
905 auto iter = process_dumps.find(pid); | 893 auto iter = process_dumps.find(pid); |
906 if (iter == process_dumps.end()) { | 894 if (iter == process_dumps.end()) { |
907 std::unique_ptr<ProcessMemoryDump> new_pmd( | 895 std::unique_ptr<ProcessMemoryDump> new_pmd( |
908 new ProcessMemoryDump(session_state, dump_args)); | 896 new ProcessMemoryDump(heap_profiler_serialization_state, dump_args)); |
909 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 897 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
910 } | 898 } |
911 return iter->second.get(); | 899 return iter->second.get(); |
912 } | 900 } |
913 | 901 |
914 } // namespace trace_event | 902 } // namespace trace_event |
915 } // namespace base | 903 } // namespace base |
OLD | NEW |