| 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; | 
| } | 
|  |