// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/resources/resource_pool.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <utility>

#include "base/atomic_sequence_num.h"
#include "base/bind.h"
#include "base/format_macros.h"
#include "base/memory/shared_memory_handle.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "base/trace_event/memory_dump_manager.h"
#include "build/build_config.h"
#include "cc/base/container_util.h"
#include "components/viz/client/client_resource_provider.h"
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/resources/resource_sizes.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"

using base::trace_event::MemoryAllocatorDump;
using base::trace_event::MemoryDumpLevelOfDetail;

namespace cc {
namespace {

// Process-unique number for each resource pool.
base::AtomicSequenceNumber g_next_tracing_id;

bool ResourceMeetsSizeRequirements(const gfx::Size& requested_size,
                                   const gfx::Size& actual_size,
                                   bool disallow_non_exact_reuse) {
  const float kReuseThreshold = 2.0f;

  if (disallow_non_exact_reuse)
    return requested_size == actual_size;

  // Allocating new resources is expensive, and we'd like to re-use our
  // existing ones within reason. Allow a larger resource to be used for a
  // smaller request.
  if (actual_size.width() < requested_size.width() ||
      actual_size.height() < requested_size.height())
    return false;

  // GetArea will crash on overflow, however all sizes in use are tile sizes.
  // These are capped at viz::ClientResourceProvider::max_texture_size(), and
  // will not overflow.
  float actual_area = actual_size.GetArea();
  float requested_area = requested_size.GetArea();
  // Don't use a resource that is more than |kReuseThreshold| times the
  // requested pixel area, as we want to free unnecessarily large resources.
  if (actual_area / requested_area > kReuseThreshold)
    return false;

  return true;
}

}  // namespace

constexpr base::TimeDelta ResourcePool::kDefaultExpirationDelay;
constexpr base::TimeDelta ResourcePool::kDefaultMaxFlushDelay;

void ResourcePool::GpuBacking::InitOverlayCandidateAndTextureTarget(
    const viz::ResourceFormat format,
    const gpu::Capabilities& caps,
    bool use_gpu_memory_buffer_resources) {
  overlay_candidate = use_gpu_memory_buffer_resources &&
                      caps.texture_storage_image &&
                      IsGpuMemoryBufferFormatSupported(format);
  if (overlay_candidate) {
    texture_target = gpu::GetBufferTextureTarget(gfx::BufferUsage::SCANOUT,
                                                 BufferFormat(format), caps);
  } else {
    texture_target = GL_TEXTURE_2D;
  }
}

ResourcePool::ResourcePool(
    viz::ClientResourceProvider* resource_provider,
    viz::ContextProvider* context_provider,
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    const base::TimeDelta& expiration_delay,
    bool disallow_non_exact_reuse)
    : resource_provider_(resource_provider),
      context_provider_(context_provider),
      task_runner_(std::move(task_runner)),
      resource_expiration_delay_(expiration_delay),
      disallow_non_exact_reuse_(disallow_non_exact_reuse),
      tracing_id_(g_next_tracing_id.GetNext()),
      flush_evicted_resources_deadline_(base::TimeTicks::Max()),
      clock_(base::DefaultTickClock::GetInstance()),
      weak_ptr_factory_(this) {
  base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
      this, "cc::ResourcePool", task_runner_.get());
  memory_pressure_listener_.reset(
      new base::MemoryPressureListener(base::BindRepeating(
          &ResourcePool::OnMemoryPressure, weak_ptr_factory_.GetWeakPtr())));
}

ResourcePool::~ResourcePool() {
  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);

  DCHECK_EQ(0u, in_use_resources_.size());

  while (!busy_resources_.empty()) {
    DidFinishUsingResource(PopBack(&busy_resources_));
  }

  SetResourceUsageLimits(0, 0);
  DCHECK_EQ(0u, unused_resources_.size());
  DCHECK_EQ(0u, in_use_memory_usage_bytes_);
  DCHECK_EQ(0u, total_memory_usage_bytes_);
  DCHECK_EQ(0u, total_resource_count_);
}

ResourcePool::PoolResource* ResourcePool::ReuseResource(
    const gfx::Size& size,
    viz::ResourceFormat format,
    const gfx::ColorSpace& color_space) {
  // Finding resources in |unused_resources_| from MRU to LRU direction, touches
  // LRU resources only if needed, which increases possibility of expiring more
  // LRU resources within kResourceExpirationDelayMs.
  for (auto it = unused_resources_.begin(); it != unused_resources_.end();
       ++it) {
    PoolResource* resource = it->get();
    DCHECK(!resource->resource_id());

    if (resource->format() != format)
      continue;
    if (!ResourceMeetsSizeRequirements(size, resource->size(),
                                       disallow_non_exact_reuse_))
      continue;
    if (resource->color_space() != color_space)
      continue;

    // Transfer resource to |in_use_resources_|.
    in_use_resources_[resource->unique_id()] = std::move(*it);
    unused_resources_.erase(it);
    in_use_memory_usage_bytes_ +=
        viz::ResourceSizes::UncheckedSizeInBytes<size_t>(resource->size(),
                                                         resource->format());
    return resource;
  }
  return nullptr;
}

ResourcePool::PoolResource* ResourcePool::CreateResource(
    const gfx::Size& size,
    viz::ResourceFormat format,
    const gfx::ColorSpace& color_space) {
  DCHECK(viz::ResourceSizes::VerifySizeInBytes<size_t>(size, format));

  auto pool_resource = std::make_unique<PoolResource>(
      next_resource_unique_id_++, size, format, color_space);

  total_memory_usage_bytes_ +=
      viz::ResourceSizes::UncheckedSizeInBytes<size_t>(size, format);
  ++total_resource_count_;

  PoolResource* resource = pool_resource.get();
  in_use_resources_[resource->unique_id()] = std::move(pool_resource);
  in_use_memory_usage_bytes_ +=
      viz::ResourceSizes::UncheckedSizeInBytes<size_t>(size, format);

  return resource;
}

ResourcePool::InUsePoolResource ResourcePool::AcquireResource(
    const gfx::Size& size,
    viz::ResourceFormat format,
    const gfx::ColorSpace& color_space) {
  PoolResource* resource = ReuseResource(size, format, color_space);
  if (!resource)
    resource = CreateResource(size, format, color_space);
  return InUsePoolResource(resource, !!context_provider_);
}

// Iterate over all three resource lists (unused, in-use, and busy), updating
// the invalidation and content IDs to allow for future partial raster. The
// first unused resource found (if any) will be returned and used for partial
// raster directly.
//
// Note that this may cause us to have multiple resources with the same content
// ID. This is not a correctness risk, as all these resources will have valid
// invalidations can can be used safely. Note that we could improve raster
// performance at the cost of search time if we found the resource with the
// smallest invalidation ID to raster in to.
ResourcePool::InUsePoolResource
ResourcePool::TryAcquireResourceForPartialRaster(
    uint64_t new_content_id,
    const gfx::Rect& new_invalidated_rect,
    uint64_t previous_content_id,
    gfx::Rect* total_invalidated_rect) {
  DCHECK(new_content_id);
  DCHECK(previous_content_id);
  *total_invalidated_rect = gfx::Rect();

  auto iter_resource_to_return = unused_resources_.end();
  int minimum_area = 0;

  // First update all unused resources. While updating, track the resource with
  // the smallest invalidation. That resource will be returned to the caller.
  for (auto it = unused_resources_.begin(); it != unused_resources_.end();
       ++it) {
    PoolResource* resource = it->get();
    if (resource->content_id() == previous_content_id) {
      UpdateResourceContentIdAndInvalidation(resource, new_content_id,
                                             new_invalidated_rect);

      // Return the resource with the smallest invalidation.
      int area =
          resource->invalidated_rect().size().GetCheckedArea().ValueOrDefault(
              std::numeric_limits<int>::max());
      if (iter_resource_to_return == unused_resources_.end() ||
          area < minimum_area) {
        iter_resource_to_return = it;
        minimum_area = area;
      }
    }
  }

  // Next, update all busy and in_use resources.
  for (const auto& resource : busy_resources_) {
    if (resource->content_id() == previous_content_id) {
      UpdateResourceContentIdAndInvalidation(resource.get(), new_content_id,
                                             new_invalidated_rect);
    }
  }
  for (const auto& resource_pair : in_use_resources_) {
    PoolResource* resource = resource_pair.second.get();
    if (resource->content_id() == previous_content_id) {
      UpdateResourceContentIdAndInvalidation(resource, new_content_id,
                                             new_invalidated_rect);
    }
  }

  // If we found an unused resource to return earlier, move it to
  // |in_use_resources_| and return it.
  if (iter_resource_to_return != unused_resources_.end()) {
    PoolResource* resource = iter_resource_to_return->get();
    DCHECK(!resource->resource_id());

    // Transfer resource to |in_use_resources_|.
    in_use_resources_[resource->unique_id()] =
        std::move(*iter_resource_to_return);
    unused_resources_.erase(iter_resource_to_return);
    in_use_memory_usage_bytes_ +=
        viz::ResourceSizes::UncheckedSizeInBytes<size_t>(resource->size(),
                                                         resource->format());
    *total_invalidated_rect = resource->invalidated_rect();

    // Clear the invalidated rect and content ID on the resource being retunred.
    // These will be updated when raster completes successfully.
    resource->set_invalidated_rect(gfx::Rect());
    resource->set_content_id(0);
    return InUsePoolResource(resource, !!context_provider_);
  }

  return InUsePoolResource();
}

void ResourcePool::OnResourceReleased(size_t unique_id,
                                      const gpu::SyncToken& sync_token,
                                      bool lost) {
  // If this fails we've removed a resource from the ResourceProvider somehow
  // while it was still in use by the ResourcePool client. That would prevent
  // the client from being able to use the ResourceId on the InUsePoolResource,
  // which would be problematic!
  DCHECK(in_use_resources_.find(unique_id) == in_use_resources_.end());

  // TODO(danakj): Should busy_resources be a map?
  auto busy_it = std::find_if(
      busy_resources_.begin(), busy_resources_.end(),
      [unique_id](const std::unique_ptr<PoolResource>& busy_resource) {
        return busy_resource->unique_id() == unique_id;
      });
  // If the resource isn't busy then we made it available for reuse already
  // somehow, even though it was exported to the ResourceProvider, or we evicted
  // a resource that was still in use by the display compositor.
  DCHECK(busy_it != busy_resources_.end());

  PoolResource* resource = busy_it->get();
  if (lost || evict_busy_resources_when_unused_ || resource->avoid_reuse()) {
    DeleteResource(std::move(*busy_it));
    busy_resources_.erase(busy_it);
    return;
  }

  resource->set_resource_id(0);
  if (context_provider_)
    resource->gpu_backing()->returned_sync_token = sync_token;
  DidFinishUsingResource(std::move(*busy_it));
  busy_resources_.erase(busy_it);
}

bool ResourcePool::PrepareForExport(const InUsePoolResource& in_use_resource) {
  PoolResource* resource = in_use_resource.resource_;
  // Exactly one of gpu or software backing should exist.
  DCHECK(resource->gpu_backing() || resource->software_backing());
  DCHECK(!resource->gpu_backing() || !resource->software_backing());
  viz::TransferableResource transferable;
  if (resource->gpu_backing()) {
    GpuBacking* gpu_backing = resource->gpu_backing();
    if (gpu_backing->mailbox.IsZero()) {
      // This can happen if we failed to allocate a GpuMemoryBuffer. Avoid
      // sending an invalid resource to the parent in that case, and avoid
      // caching/reusing the resource.
      resource->set_resource_id(0);
      resource->mark_avoid_reuse();
      return false;
    }
    transferable = viz::TransferableResource::MakeGLOverlay(
        gpu_backing->mailbox, GL_LINEAR, gpu_backing->texture_target,
        gpu_backing->mailbox_sync_token, resource->size(),
        gpu_backing->overlay_candidate);
    transferable.read_lock_fences_enabled = gpu_backing->wait_on_fence_required;
  } else {
    transferable = viz::TransferableResource::MakeSoftware(
        resource->software_backing()->shared_bitmap_id, resource->size(),
        resource->format());
  }
  transferable.format = resource->format();
  transferable.color_space = resource->color_space();
  resource->set_resource_id(resource_provider_->ImportResource(
      std::move(transferable),
      viz::SingleReleaseCallback::Create(base::BindOnce(
          &ResourcePool::OnResourceReleased, weak_ptr_factory_.GetWeakPtr(),
          resource->unique_id()))));
  return true;
}

void ResourcePool::InvalidateResources() {
  while (!unused_resources_.empty())
    DeleteResource(PopBack(&unused_resources_));
  for (auto& pool_resource : busy_resources_)
    pool_resource->mark_avoid_reuse();
  for (auto& pair : in_use_resources_)
    pair.second->mark_avoid_reuse();
}

void ResourcePool::ReleaseResource(InUsePoolResource in_use_resource) {
  PoolResource* pool_resource = in_use_resource.resource_;
  in_use_resource.SetWasFreedByResourcePool();

  // Ensure that the provided resource is valid.
  // TODO(ericrk): Remove this once we've investigated further.
  // crbug.com/598286.
  CHECK(pool_resource);

  auto it = in_use_resources_.find(pool_resource->unique_id());
  if (it == in_use_resources_.end()) {
    // We should never hit this. Do some digging to try to determine the cause.
    // TODO(ericrk): Remove this once we've investigated further.
    // crbug.com/598286.

    // Maybe this is a double free - see if the resource exists in our busy
    // list.
    auto found_busy = std::find_if(
        busy_resources_.begin(), busy_resources_.end(),
        [pool_resource](const std::unique_ptr<PoolResource>& busy_resource) {
          return busy_resource->unique_id() == pool_resource->unique_id();
        });
    CHECK(found_busy == busy_resources_.end());

    // Also check if the resource exists in our unused resources list.
    auto found_unused = std::find_if(
        unused_resources_.begin(), unused_resources_.end(),
        [pool_resource](const std::unique_ptr<PoolResource>& unused_resource) {
          return unused_resource->unique_id() == pool_resource->unique_id();
        });
    CHECK(found_unused == unused_resources_.end());

    // Resource doesn't exist in any of our lists. CHECK.
    CHECK(false);
  }

  // Also ensure that the resource wasn't null in our list.
  // TODO(ericrk): Remove this once we've investigated further.
  // crbug.com/598286.
  CHECK(it->second.get());

  pool_resource->set_last_usage(clock_->NowTicks());
  in_use_memory_usage_bytes_ -=
      viz::ResourceSizes::UncheckedSizeInBytes<size_t>(pool_resource->size(),
                                                       pool_resource->format());

  // Save the ResourceId since the |pool_resource| can be deleted in the next
  // step.
  viz::ResourceId resource_id = pool_resource->resource_id();

  // Transfer resource to |unused_resources_| or |busy_resources_|, depending if
  // it was exported to the ResourceProvider via PrepareForExport(). If not,
  // then we can immediately make the resource available to be reused, unless it
  // was marked not for reuse.
  if (resource_id)
    busy_resources_.push_front(std::move(it->second));
  else if (pool_resource->avoid_reuse())
    DeleteResource(std::move(it->second));  // This deletes |pool_resource|.
  else
    DidFinishUsingResource(std::move(it->second));
  in_use_resources_.erase(it);

  // If the resource was exported, then it has a resource id. By removing the
  // resource id, we will be notified in the ReleaseCallback when the resource
  // is no longer exported and can be reused.
  if (resource_id)
    resource_provider_->RemoveImportedResource(resource_id);

  // Now that we have evictable resources, schedule an eviction call for this
  // resource if necessary.
  ScheduleEvictExpiredResourcesIn(resource_expiration_delay_);
}

void ResourcePool::OnContentReplaced(
    const ResourcePool::InUsePoolResource& in_use_resource,
    uint64_t content_id) {
  PoolResource* resource = in_use_resource.resource_;
  DCHECK(resource);
  resource->set_content_id(content_id);
  resource->set_invalidated_rect(gfx::Rect());
}

void ResourcePool::SetResourceUsageLimits(size_t max_memory_usage_bytes,
                                          size_t max_resource_count) {
  max_memory_usage_bytes_ = max_memory_usage_bytes;
  max_resource_count_ = max_resource_count;

  ReduceResourceUsage();
}

void ResourcePool::ReduceResourceUsage() {
  while (!unused_resources_.empty()) {
    if (!ResourceUsageTooHigh())
      break;

    // LRU eviction pattern. Most recently used might be blocked by
    // a read lock fence but it's still better to evict the least
    // recently used as it prevents a resource that is hard to reuse
    // because of unique size from being kept around. Resources that
    // can't be locked for write might also not be truly free-able.
    // We can free the resource here but it doesn't mean that the
    // memory is necessarily returned to the OS.
    DeleteResource(PopBack(&unused_resources_));
  }
}

bool ResourcePool::ResourceUsageTooHigh() {
  if (total_resource_count_ > max_resource_count_)
    return true;
  if (total_memory_usage_bytes_ > max_memory_usage_bytes_)
    return true;
  return false;
}

void ResourcePool::DeleteResource(std::unique_ptr<PoolResource> resource) {
  size_t resource_bytes = viz::ResourceSizes::UncheckedSizeInBytes<size_t>(
      resource->size(), resource->format());
  total_memory_usage_bytes_ -= resource_bytes;
  --total_resource_count_;
  if (flush_evicted_resources_deadline_ == base::TimeTicks::Max()) {
    flush_evicted_resources_deadline_ =
        clock_->NowTicks() + kDefaultMaxFlushDelay;
  }
}

void ResourcePool::UpdateResourceContentIdAndInvalidation(
    PoolResource* resource,
    uint64_t new_content_id,
    const gfx::Rect& new_invalidated_rect) {
  gfx::Rect updated_invalidated_rect = new_invalidated_rect;
  if (!resource->invalidated_rect().IsEmpty())
    updated_invalidated_rect.Union(resource->invalidated_rect());

  resource->set_content_id(new_content_id);
  resource->set_invalidated_rect(updated_invalidated_rect);
}

void ResourcePool::DidFinishUsingResource(
    std::unique_ptr<PoolResource> resource) {
  unused_resources_.push_front(std::move(resource));
}

void ResourcePool::ScheduleEvictExpiredResourcesIn(
    base::TimeDelta time_from_now) {
  if (evict_expired_resources_pending_)
    return;

  evict_expired_resources_pending_ = true;

  task_runner_->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&ResourcePool::EvictExpiredResources,
                     weak_ptr_factory_.GetWeakPtr()),
      time_from_now);
}

void ResourcePool::EvictExpiredResources() {
  evict_expired_resources_pending_ = false;
  base::TimeTicks current_time = clock_->NowTicks();

  EvictResourcesNotUsedSince(current_time - resource_expiration_delay_);

  if (unused_resources_.empty() ||
      flush_evicted_resources_deadline_ <= current_time) {
    // If nothing is evictable, we have deleted one (and possibly more)
    // resources without any new activity. Flush to ensure these deletions are
    // processed.
    FlushEvictedResources();
  }

  if (!unused_resources_.empty()) {
    // If we still have evictable resources, schedule a call to
    // EvictExpiredResources for either (a) the time when the LRU buffer expires
    // or (b) the deadline to explicitly flush previously evicted resources.
    ScheduleEvictExpiredResourcesIn(
        std::min(GetUsageTimeForLRUResource() + resource_expiration_delay_,
                 flush_evicted_resources_deadline_) -
        current_time);
  }
}

void ResourcePool::EvictResourcesNotUsedSince(base::TimeTicks time_limit) {
  while (!unused_resources_.empty()) {
    // |unused_resources_| is not strictly ordered with regards to last_usage,
    // as this may not exactly line up with the time a resource became non-busy.
    // However, this should be roughly ordered, and will only introduce slight
    // delays in freeing expired resources.
    if (unused_resources_.back()->last_usage() > time_limit)
      return;

    DeleteResource(PopBack(&unused_resources_));
  }
}

base::TimeTicks ResourcePool::GetUsageTimeForLRUResource() const {
  if (!unused_resources_.empty()) {
    return unused_resources_.back()->last_usage();
  }

  // This is only called when we have at least one evictable resource.
  DCHECK(!busy_resources_.empty());
  return busy_resources_.back()->last_usage();
}

void ResourcePool::FlushEvictedResources() {
  flush_evicted_resources_deadline_ = base::TimeTicks::Max();
  if (context_provider_) {
    // Flush any ContextGL work as well as any SharedImageInterface work.
    context_provider_->ContextGL()->OrderingBarrierCHROMIUM();
    context_provider_->ContextSupport()->FlushPendingWork();
  }
}

bool ResourcePool::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                                base::trace_event::ProcessMemoryDump* pmd) {
  if (args.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND) {
    std::string dump_name =
        base::StringPrintf("cc/tile_memory/provider_%d", tracing_id_);
    MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
    dump->AddScalar(MemoryAllocatorDump::kNameSize,
                    MemoryAllocatorDump::kUnitsBytes,
                    total_memory_usage_bytes_);
  } else {
    for (const auto& resource : unused_resources_) {
      resource->OnMemoryDump(pmd, tracing_id_, resource_provider_,
                             true /* is_free */);
    }
    for (const auto& resource : busy_resources_) {
      resource->OnMemoryDump(pmd, tracing_id_, resource_provider_,
                             false /* is_free */);
    }
    for (const auto& entry : in_use_resources_) {
      entry.second->OnMemoryDump(pmd, tracing_id_, resource_provider_,
                                 false /* is_free */);
    }
  }
  return true;
}

void ResourcePool::OnMemoryPressure(
    base::MemoryPressureListener::MemoryPressureLevel level) {
  switch (level) {
    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
      break;
    case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
      EvictResourcesNotUsedSince(base::TimeTicks() + base::TimeDelta::Max());
      FlushEvictedResources();
      break;
  }
}

ResourcePool::PoolResource::PoolResource(size_t unique_id,
                                         const gfx::Size& size,
                                         viz::ResourceFormat format,
                                         const gfx::ColorSpace& color_space)
    : unique_id_(unique_id),
      size_(size),
      format_(format),
      color_space_(color_space) {}

ResourcePool::PoolResource::~PoolResource() = default;

void ResourcePool::PoolResource::OnMemoryDump(
    base::trace_event::ProcessMemoryDump* pmd,
    int tracing_id,
    const viz::ClientResourceProvider* resource_provider,
    bool is_free) const {
  // Resource IDs are not process-unique, so log with the ResourcePool's unique
  // tracing id.
  std::string dump_name = base::StringPrintf(
      "cc/tile_memory/provider_%d/resource_%zd", tracing_id, unique_id_);
  MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);

  // The importance value used here needs to be greater than the importance
  // used in other places that use this GUID to inform the system that this is
  // the root ownership. The gpu processes uses 0, so 2 is sufficient, and was
  // chosen historically and there is no need to adjust it.
  const int kImportance = 2;
  auto* dump_manager = base::trace_event::MemoryDumpManager::GetInstance();
  uint64_t tracing_process_id = dump_manager->GetTracingProcessId();
  if (software_backing_) {
    software_backing_->OnMemoryDump(pmd, dump->guid(), tracing_process_id,
                                    kImportance);
  } else if (gpu_backing_) {
    gpu_backing_->OnMemoryDump(pmd, dump->guid(), tracing_process_id,
                               kImportance);
  }

  uint64_t total_bytes =
      viz::ResourceSizes::UncheckedSizeInBytesAligned<size_t>(size_, format_);
  dump->AddScalar(MemoryAllocatorDump::kNameSize,
                  MemoryAllocatorDump::kUnitsBytes, total_bytes);

  if (is_free) {
    dump->AddScalar("free_size", MemoryAllocatorDump::kUnitsBytes, total_bytes);
  }
}

}  // namespace cc
