blob: 57fa91b9304788a9e01273d1f05aa34e12952ef7 [file] [log] [blame]
ssid83aa5be2015-05-08 12:03:261// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "gin/v8_isolate_memory_dump_provider.h"
6
ssid83aa5be2015-05-08 12:03:267#include "base/strings/stringprintf.h"
8#include "base/thread_task_runner_handle.h"
9#include "base/trace_event/memory_dump_manager.h"
10#include "base/trace_event/process_memory_dump.h"
11#include "gin/public/isolate_holder.h"
12#include "v8/include/v8.h"
13
14namespace gin {
15
16namespace {
ssid83aa5be2015-05-08 12:03:2617const char kHeapSpacesDumpName[] = "heap_spaces";
ssidf51216b02015-06-04 19:46:2318const char kHeapObjectsDumpName[] = "heap_objects";
ssid83aa5be2015-05-08 12:03:2619const char kAvailableSizeAttribute[] = "available_size_in_bytes";
20} // namespace
21
22V8IsolateMemoryDumpProvider::V8IsolateMemoryDumpProvider(
23 IsolateHolder* isolate_holder)
24 : isolate_holder_(isolate_holder) {
25 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
26 this, base::ThreadTaskRunnerHandle::Get());
27}
28
29V8IsolateMemoryDumpProvider::~V8IsolateMemoryDumpProvider() {
30 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
31 this);
32}
33
34// Called at trace dump point time. Creates a snapshot with the memory counters
35// for the current isolate.
36bool V8IsolateMemoryDumpProvider::OnMemoryDump(
ssidf51216b02015-06-04 19:46:2337 base::trace_event::ProcessMemoryDump* process_memory_dump) {
38 std::string dump_base_name =
39 base::StringPrintf("v8/isolate_%p", isolate_holder_->isolate());
40 std::string space_dump_name = dump_base_name + "/" + kHeapSpacesDumpName;
41 std::string object_dump_name = dump_base_name + "/" + kHeapObjectsDumpName;
42 process_memory_dump->AddOwnershipEdge(
43 process_memory_dump->CreateAllocatorDump(object_dump_name)->guid(),
44 process_memory_dump->CreateAllocatorDump(space_dump_name)->guid());
45
ssid83aa5be2015-05-08 12:03:2646 if (isolate_holder_->access_mode() == IsolateHolder::kUseLocker) {
47 v8::Locker locked(isolate_holder_->isolate());
ssidf51216b02015-06-04 19:46:2348 DumpHeapSpacesStatistics(process_memory_dump, space_dump_name);
49 DumpHeapObjectStatistics(process_memory_dump, object_dump_name);
ssid83aa5be2015-05-08 12:03:2650 } else {
ssidf51216b02015-06-04 19:46:2351 DumpHeapSpacesStatistics(process_memory_dump, space_dump_name);
52 DumpHeapObjectStatistics(process_memory_dump, object_dump_name);
ssid83aa5be2015-05-08 12:03:2653 }
54 return true;
55}
56
ssidf51216b02015-06-04 19:46:2357void V8IsolateMemoryDumpProvider::DumpHeapSpacesStatistics(
58 base::trace_event::ProcessMemoryDump* process_memory_dump,
59 const std::string& dump_base_name) {
ssid83aa5be2015-05-08 12:03:2660 v8::HeapStatistics heap_statistics;
61 isolate_holder_->isolate()->GetHeapStatistics(&heap_statistics);
62
63 size_t known_spaces_used_size = 0;
64 size_t known_spaces_size = 0;
ssid49aa14c72015-05-29 13:03:5965 size_t known_spaces_available_size = 0;
ssid83aa5be2015-05-08 12:03:2666 size_t number_of_spaces = isolate_holder_->isolate()->NumberOfHeapSpaces();
67 for (size_t space = 0; space < number_of_spaces; space++) {
68 v8::HeapSpaceStatistics space_statistics;
69 isolate_holder_->isolate()->GetHeapSpaceStatistics(&space_statistics,
70 space);
71 const size_t space_size = space_statistics.space_size();
72 const size_t space_used_size = space_statistics.space_used_size();
ssid49aa14c72015-05-29 13:03:5973 const size_t space_available_size = space_statistics.space_available_size();
ssid83aa5be2015-05-08 12:03:2674
75 known_spaces_size += space_size;
76 known_spaces_used_size += space_used_size;
ssid49aa14c72015-05-29 13:03:5977 known_spaces_available_size += space_available_size;
ssid83aa5be2015-05-08 12:03:2678
ssid83aa5be2015-05-08 12:03:2679 base::trace_event::MemoryAllocatorDump* space_dump =
ssidf51216b02015-06-04 19:46:2380 process_memory_dump->CreateAllocatorDump(dump_base_name + "/" +
81 space_statistics.space_name());
ssid83aa5be2015-05-08 12:03:2682 space_dump->AddScalar(
83 base::trace_event::MemoryAllocatorDump::kNameOuterSize,
84 base::trace_event::MemoryAllocatorDump::kUnitsBytes, space_size);
ssid83aa5be2015-05-08 12:03:2685 space_dump->AddScalar(
86 base::trace_event::MemoryAllocatorDump::kNameInnerSize,
87 base::trace_event::MemoryAllocatorDump::kUnitsBytes, space_used_size);
88 space_dump->AddScalar(kAvailableSizeAttribute,
89 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
ssid49aa14c72015-05-29 13:03:5990 space_available_size);
ssid83aa5be2015-05-08 12:03:2691 }
ssidf51216b02015-06-04 19:46:2392
ssid83aa5be2015-05-08 12:03:2693 // Compute the rest of the memory, not accounted by the spaces above.
ssid83aa5be2015-05-08 12:03:2694 base::trace_event::MemoryAllocatorDump* other_spaces_dump =
ssidf51216b02015-06-04 19:46:2395 process_memory_dump->CreateAllocatorDump(dump_base_name +
96 "/other_spaces");
ssid83aa5be2015-05-08 12:03:2697 other_spaces_dump->AddScalar(
98 base::trace_event::MemoryAllocatorDump::kNameOuterSize,
99 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
100 heap_statistics.total_heap_size() - known_spaces_size);
101 other_spaces_dump->AddScalar(
102 base::trace_event::MemoryAllocatorDump::kNameInnerSize,
103 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
104 heap_statistics.used_heap_size() - known_spaces_used_size);
105
ssid83aa5be2015-05-08 12:03:26106 other_spaces_dump->AddScalar(
107 kAvailableSizeAttribute,
ssid49aa14c72015-05-29 13:03:59108 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
109 heap_statistics.total_available_size() - known_spaces_available_size);
ssid83aa5be2015-05-08 12:03:26110}
111
ssidf51216b02015-06-04 19:46:23112void V8IsolateMemoryDumpProvider::DumpHeapObjectStatistics(
113 base::trace_event::ProcessMemoryDump* process_memory_dump,
114 const std::string& dump_base_name) {
115 const size_t object_types =
116 isolate_holder_->isolate()->NumberOfTrackedHeapObjectTypes();
117 for (size_t type_index = 0; type_index < object_types; type_index++) {
118 v8::HeapObjectStatistics object_statistics;
119 if (!isolate_holder_->isolate()->GetHeapObjectStatisticsAtLastGC(
120 &object_statistics, type_index))
121 continue;
122
123 std::string dump_name =
124 dump_base_name + "/" + object_statistics.object_type();
125 if (object_statistics.object_sub_type()[0] != '\0')
126 dump_name += std::string("/") + object_statistics.object_sub_type();
127 base::trace_event::MemoryAllocatorDump* object_dump =
128 process_memory_dump->CreateAllocatorDump(dump_name);
129
130 object_dump->AddScalar(
131 base::trace_event::MemoryAllocatorDump::kNameObjectsCount,
132 base::trace_event::MemoryAllocatorDump::kUnitsObjects,
133 object_statistics.object_count());
134 object_dump->AddScalar(
135 base::trace_event::MemoryAllocatorDump::kNameInnerSize,
136 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
137 object_statistics.object_size());
138 }
139
140 process_memory_dump->AddOwnershipEdge(
141 process_memory_dump->CreateAllocatorDump(dump_base_name +
142 "/CODE_TYPE/CODE_KIND")->guid(),
143 process_memory_dump->CreateAllocatorDump(dump_base_name +
144 "/CODE_TYPE/CODE_AGE")->guid());
145}
146
ssid83aa5be2015-05-08 12:03:26147} // namespace gin