blob: 8666fd0985325d117725dcbf3b672821947170ec [file] [log] [blame]
// Copyright 2015 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 "content/child/web_memory_dump_provider_adapter.h"
#include "base/lazy_instance.h"
#include "base/synchronization/lock.h"
#include "base/trace_event/memory_profiler_allocation_register.h"
#include "base/trace_event/memory_profiler_heap_dump_writer.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event_argument.h"
#include "base/trace_event/trace_event_memory_overhead.h"
#include "content/child/web_process_memory_dump_impl.h"
#include "third_party/WebKit/public/platform/WebMemoryDumpProvider.h"
using namespace base;
using namespace base::trace_event;
namespace {
// TODO(ruuda): Move these into the dump providers once Blink can depend on
// base. See https://crbug.com/548254.
AllocationRegister* g_allocation_register = nullptr;
LazyInstance<Lock>::Leaky g_allocation_register_lock =
LAZY_INSTANCE_INITIALIZER;
bool g_heap_profiling_enabled = false;
void ReportAllocation(void* address, size_t size) {
AllocationContext context = AllocationContextTracker::GetContextSnapshot();
AutoLock lock(g_allocation_register_lock.Get());
if (g_allocation_register)
g_allocation_register->Insert(address, size, context);
}
void ReportFree(void* address) {
AutoLock lock(g_allocation_register_lock.Get());
if (g_allocation_register)
g_allocation_register->Remove(address);
}
} // namespace
namespace content {
WebMemoryDumpProviderAdapter::WebMemoryDumpProviderAdapter(
blink::WebMemoryDumpProvider* wmdp)
: web_memory_dump_provider_(wmdp), is_registered_(false) {
}
WebMemoryDumpProviderAdapter::~WebMemoryDumpProviderAdapter() {
DCHECK(!is_registered_);
}
bool WebMemoryDumpProviderAdapter::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) {
blink::WebMemoryDumpLevelOfDetail level;
switch (args.level_of_detail) {
case base::trace_event::MemoryDumpLevelOfDetail::LIGHT:
level = blink::WebMemoryDumpLevelOfDetail::Light;
break;
case base::trace_event::MemoryDumpLevelOfDetail::DETAILED:
level = blink::WebMemoryDumpLevelOfDetail::Detailed;
break;
default:
NOTREACHED();
return false;
}
WebProcessMemoryDumpImpl web_pmd_impl(args.level_of_detail, pmd);
if (args.level_of_detail == MemoryDumpLevelOfDetail::DETAILED &&
web_memory_dump_provider_->supportsHeapProfiling() &&
g_heap_profiling_enabled) {
HeapDumpWriter writer(pmd->session_state()->stack_frame_deduplicator());
TraceEventMemoryOverhead overhead;
{
AutoLock lock(g_allocation_register_lock.Get());
for (const auto& alloc_size : *g_allocation_register)
writer.InsertAllocation(alloc_size.context, alloc_size.size);
g_allocation_register->EstimateTraceMemoryOverhead(&overhead);
}
pmd->AddHeapDump("partition_alloc", writer.WriteHeapDump());
overhead.DumpInto("tracing/heap_profiler", pmd);
}
return web_memory_dump_provider_->onMemoryDump(level, &web_pmd_impl);
}
void WebMemoryDumpProviderAdapter::OnHeapProfilingEnabled(bool enabled) {
if (!web_memory_dump_provider_->supportsHeapProfiling())
return;
if (enabled) {
{
AutoLock lock(g_allocation_register_lock.Get());
if (!g_allocation_register)
g_allocation_register = new AllocationRegister();
}
// Make this dump provider call the global hooks on every allocation / free.
// TODO(ruuda): Because bookkeeping is done here in the adapter, and not in
// the dump providers themselves, all dump providers in Blink share the
// same global allocation register. At the moment this is not a problem,
// because the only dump provider that supports heap profiling is the
// PartitionAlloc dump provider. When Blink can depend on base and this
// glue layer is removed, dump providers can have their own instance of the
// allocation register. Tracking bug: https://crbug.com/548254.
web_memory_dump_provider_->onHeapProfilingEnabled(ReportAllocation,
ReportFree);
} else {
web_memory_dump_provider_->onHeapProfilingEnabled(nullptr, nullptr);
}
g_heap_profiling_enabled = enabled;
}
} // namespace content