Index: components/tracing/common/process_metrics_memory_dump_provider.cc |
diff --git a/components/tracing/common/process_metrics_memory_dump_provider.cc b/components/tracing/common/process_metrics_memory_dump_provider.cc |
index a9fe6b5aa74e9083309eb3d3adb74a07a51c90b3..2936256acd3afbde8d91a9472877fe50f0f7c403 100644 |
--- a/components/tracing/common/process_metrics_memory_dump_provider.cc |
+++ b/components/tracing/common/process_metrics_memory_dump_provider.cc |
@@ -36,6 +36,7 @@ |
#include <mach/mach.h> |
#include "base/numerics/safe_math.h" |
+#include "base/process/process_metrics.h" |
#endif // defined(OS_MACOSX) |
#if defined(OS_WIN) |
@@ -387,31 +388,20 @@ bool GetDyldRegions(std::vector<VMRegion>* regions) { |
return true; |
} |
-void PopulateByteStats(VMRegion* region, const vm_region_submap_info_64& info) { |
- uint32_t share_mode = info.share_mode; |
- if (share_mode == SM_COW && info.ref_count == 1) |
- share_mode = SM_PRIVATE; |
- |
- uint64_t dirty_bytes = info.pages_dirtied * PAGE_SIZE; |
- uint64_t clean_bytes = |
- (info.pages_resident - info.pages_reusable - info.pages_dirtied) * |
- PAGE_SIZE; |
- switch (share_mode) { |
+void PopulateByteStats(VMRegion* region, |
+ const vm_region_top_info_data_t& info) { |
+ uint64_t dirty_bytes = |
+ (info.private_pages_resident + info.shared_pages_resident) * PAGE_SIZE; |
+ switch (info.share_mode) { |
case SM_LARGE_PAGE: |
case SM_PRIVATE: |
- region->byte_stats_private_dirty_resident = dirty_bytes; |
- region->byte_stats_private_clean_resident = clean_bytes; |
- break; |
case SM_COW: |
region->byte_stats_private_dirty_resident = dirty_bytes; |
- region->byte_stats_shared_clean_resident = clean_bytes; |
- break; |
case SM_SHARED: |
case SM_PRIVATE_ALIASED: |
case SM_TRUESHARED: |
case SM_SHARED_ALIASED: |
region->byte_stats_shared_dirty_resident = dirty_bytes; |
- region->byte_stats_shared_clean_resident = clean_bytes; |
break; |
case SM_EMPTY: |
break; |
@@ -421,39 +411,45 @@ void PopulateByteStats(VMRegion* region, const vm_region_submap_info_64& info) { |
} |
} |
-// Creates VMRegions from mach_vm_region_recurse. Returns whether the operation |
+// Creates VMRegions using mach vm syscalls. Returns whether the operation |
// succeeded. |
bool GetAllRegions(std::vector<VMRegion>* regions) { |
const int pid = getpid(); |
task_t task = mach_task_self(); |
mach_vm_size_t size = 0; |
- vm_region_submap_info_64 info; |
- natural_t depth = 1; |
- mach_msg_type_number_t count = sizeof(info); |
mach_vm_address_t address = MACH_VM_MIN_ADDRESS; |
while (true) { |
- memset(&info, 0, sizeof(info)); |
- kern_return_t kr = mach_vm_region_recurse( |
- task, &address, &size, &depth, |
- reinterpret_cast<vm_region_info_t>(&info), &count); |
- if (kr == KERN_INVALID_ADDRESS) // nothing else left |
+ base::CheckedNumeric<mach_vm_address_t> next_address(address); |
+ next_address += size; |
+ if (!next_address.IsValid()) |
+ return false; |
+ address = next_address.ValueOrDie(); |
+ mach_vm_address_t address_copy = address; |
+ |
+ vm_region_top_info_data_t info; |
+ base::MachVMRegionResult result = |
+ base::GetTopInfo(task, &size, &address, &info); |
+ if (result == base::MachVMRegionResult::Error) |
+ return false; |
+ if (result == base::MachVMRegionResult::Finished) |
break; |
- if (kr != KERN_SUCCESS) // something bad |
+ |
+ vm_region_basic_info_64 basic_info; |
+ mach_vm_size_t dummy_size = 0; |
+ result = base::GetBasicInfo(task, &dummy_size, &address_copy, &basic_info); |
+ if (result == base::MachVMRegionResult::Error) |
return false; |
- if (info.is_submap) { |
- size = 0; |
- ++depth; |
- continue; |
- } |
+ if (result == base::MachVMRegionResult::Finished) |
+ break; |
VMRegion region; |
PopulateByteStats(®ion, info); |
- if (info.protection & VM_PROT_READ) |
+ if (basic_info.protection & VM_PROT_READ) |
region.protection_flags |= VMRegion::kProtectionFlagsRead; |
- if (info.protection & VM_PROT_WRITE) |
+ if (basic_info.protection & VM_PROT_WRITE) |
region.protection_flags |= VMRegion::kProtectionFlagsWrite; |
- if (info.protection & VM_PROT_EXECUTE) |
+ if (basic_info.protection & VM_PROT_EXECUTE) |
region.protection_flags |= VMRegion::kProtectionFlagsExec; |
char buffer[MAXPATHLEN]; |
@@ -461,16 +457,12 @@ bool GetAllRegions(std::vector<VMRegion>* regions) { |
if (length != 0) |
region.mapped_file.assign(buffer, length); |
- region.byte_stats_swapped = info.pages_swapped_out * PAGE_SIZE; |
+ // There's no way to get swapped or clean bytes without doing a |
+ // very expensive syscalls that crawls every single page in the memory |
+ // object. |
region.start_address = address; |
region.size_in_bytes = size; |
regions->push_back(region); |
- |
- base::CheckedNumeric<mach_vm_address_t> numeric(address); |
- numeric += size; |
- if (!numeric.IsValid()) |
- return false; |
- address = numeric.ValueOrDie(); |
} |
return true; |
} |