Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/inspector/V8HeapProfilerAgentImpl.cpp

Issue 2338413003: [inspector] change implementation file extension from cpp to cc (Closed)
Patch Set: string16 -> string-16 Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/inspector/V8HeapProfilerAgentImpl.h ('k') | src/inspector/V8InjectedScriptHost.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 the V8 project 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 "src/inspector/V8HeapProfilerAgentImpl.h"
6
7 #include "src/inspector/InjectedScript.h"
8 #include "src/inspector/StringUtil.h"
9 #include "src/inspector/V8Debugger.h"
10 #include "src/inspector/V8InspectorImpl.h"
11 #include "src/inspector/V8InspectorSessionImpl.h"
12 #include "src/inspector/protocol/Protocol.h"
13
14 #include "include/v8-inspector.h"
15 #include "include/v8-profiler.h"
16 #include "include/v8-version.h"
17
18 namespace v8_inspector {
19
20 namespace {
21
22 namespace HeapProfilerAgentState {
23 static const char heapProfilerEnabled[] = "heapProfilerEnabled";
24 static const char heapObjectsTrackingEnabled[] = "heapObjectsTrackingEnabled";
25 static const char allocationTrackingEnabled[] = "allocationTrackingEnabled";
26 static const char samplingHeapProfilerEnabled[] = "samplingHeapProfilerEnabled";
27 static const char samplingHeapProfilerInterval[] =
28 "samplingHeapProfilerInterval";
29 }
30
31 class HeapSnapshotProgress final : public v8::ActivityControl {
32 public:
33 HeapSnapshotProgress(protocol::HeapProfiler::Frontend* frontend)
34 : m_frontend(frontend) {}
35 ControlOption ReportProgressValue(int done, int total) override {
36 m_frontend->reportHeapSnapshotProgress(done, total,
37 protocol::Maybe<bool>());
38 if (done >= total) {
39 m_frontend->reportHeapSnapshotProgress(total, total, true);
40 }
41 m_frontend->flush();
42 return kContinue;
43 }
44
45 private:
46 protocol::HeapProfiler::Frontend* m_frontend;
47 };
48
49 class GlobalObjectNameResolver final
50 : public v8::HeapProfiler::ObjectNameResolver {
51 public:
52 explicit GlobalObjectNameResolver(V8InspectorSessionImpl* session)
53 : m_offset(0), m_strings(10000), m_session(session) {}
54
55 const char* GetName(v8::Local<v8::Object> object) override {
56 InspectedContext* context = m_session->inspector()->getContext(
57 m_session->contextGroupId(),
58 V8Debugger::contextId(object->CreationContext()));
59 if (!context) return "";
60 String16 name = context->origin();
61 size_t length = name.length();
62 if (m_offset + length + 1 >= m_strings.size()) return "";
63 for (size_t i = 0; i < length; ++i) {
64 UChar ch = name[i];
65 m_strings[m_offset + i] = ch > 0xff ? '?' : static_cast<char>(ch);
66 }
67 m_strings[m_offset + length] = '\0';
68 char* result = &*m_strings.begin() + m_offset;
69 m_offset += length + 1;
70 return result;
71 }
72
73 private:
74 size_t m_offset;
75 std::vector<char> m_strings;
76 V8InspectorSessionImpl* m_session;
77 };
78
79 class HeapSnapshotOutputStream final : public v8::OutputStream {
80 public:
81 HeapSnapshotOutputStream(protocol::HeapProfiler::Frontend* frontend)
82 : m_frontend(frontend) {}
83 void EndOfStream() override {}
84 int GetChunkSize() override { return 102400; }
85 WriteResult WriteAsciiChunk(char* data, int size) override {
86 m_frontend->addHeapSnapshotChunk(String16(data, size));
87 m_frontend->flush();
88 return kContinue;
89 }
90
91 private:
92 protocol::HeapProfiler::Frontend* m_frontend;
93 };
94
95 v8::Local<v8::Object> objectByHeapObjectId(v8::Isolate* isolate, int id) {
96 v8::HeapProfiler* profiler = isolate->GetHeapProfiler();
97 v8::Local<v8::Value> value = profiler->FindObjectById(id);
98 if (value.IsEmpty() || !value->IsObject()) return v8::Local<v8::Object>();
99 return value.As<v8::Object>();
100 }
101
102 class InspectableHeapObject final : public V8InspectorSession::Inspectable {
103 public:
104 explicit InspectableHeapObject(int heapObjectId)
105 : m_heapObjectId(heapObjectId) {}
106 v8::Local<v8::Value> get(v8::Local<v8::Context> context) override {
107 return objectByHeapObjectId(context->GetIsolate(), m_heapObjectId);
108 }
109
110 private:
111 int m_heapObjectId;
112 };
113
114 class HeapStatsStream final : public v8::OutputStream {
115 public:
116 HeapStatsStream(protocol::HeapProfiler::Frontend* frontend)
117 : m_frontend(frontend) {}
118
119 void EndOfStream() override {}
120
121 WriteResult WriteAsciiChunk(char* data, int size) override {
122 DCHECK(false);
123 return kAbort;
124 }
125
126 WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* updateData,
127 int count) override {
128 DCHECK_GT(count, 0);
129 std::unique_ptr<protocol::Array<int>> statsDiff =
130 protocol::Array<int>::create();
131 for (int i = 0; i < count; ++i) {
132 statsDiff->addItem(updateData[i].index);
133 statsDiff->addItem(updateData[i].count);
134 statsDiff->addItem(updateData[i].size);
135 }
136 m_frontend->heapStatsUpdate(std::move(statsDiff));
137 return kContinue;
138 }
139
140 private:
141 protocol::HeapProfiler::Frontend* m_frontend;
142 };
143
144 } // namespace
145
146 V8HeapProfilerAgentImpl::V8HeapProfilerAgentImpl(
147 V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel,
148 protocol::DictionaryValue* state)
149 : m_session(session),
150 m_isolate(session->inspector()->isolate()),
151 m_frontend(frontendChannel),
152 m_state(state),
153 m_hasTimer(false) {}
154
155 V8HeapProfilerAgentImpl::~V8HeapProfilerAgentImpl() {}
156
157 void V8HeapProfilerAgentImpl::restore() {
158 if (m_state->booleanProperty(HeapProfilerAgentState::heapProfilerEnabled,
159 false))
160 m_frontend.resetProfiles();
161 if (m_state->booleanProperty(
162 HeapProfilerAgentState::heapObjectsTrackingEnabled, false))
163 startTrackingHeapObjectsInternal(m_state->booleanProperty(
164 HeapProfilerAgentState::allocationTrackingEnabled, false));
165 if (m_state->booleanProperty(
166 HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) {
167 ErrorString error;
168 double samplingInterval = m_state->doubleProperty(
169 HeapProfilerAgentState::samplingHeapProfilerInterval, -1);
170 DCHECK_GE(samplingInterval, 0);
171 startSampling(&error, Maybe<double>(samplingInterval));
172 }
173 }
174
175 void V8HeapProfilerAgentImpl::collectGarbage(ErrorString*) {
176 m_isolate->LowMemoryNotification();
177 }
178
179 void V8HeapProfilerAgentImpl::startTrackingHeapObjects(
180 ErrorString*, const protocol::Maybe<bool>& trackAllocations) {
181 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true);
182 bool allocationTrackingEnabled = trackAllocations.fromMaybe(false);
183 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled,
184 allocationTrackingEnabled);
185 startTrackingHeapObjectsInternal(allocationTrackingEnabled);
186 }
187
188 void V8HeapProfilerAgentImpl::stopTrackingHeapObjects(
189 ErrorString* error, const protocol::Maybe<bool>& reportProgress) {
190 requestHeapStatsUpdate();
191 takeHeapSnapshot(error, reportProgress);
192 stopTrackingHeapObjectsInternal();
193 }
194
195 void V8HeapProfilerAgentImpl::enable(ErrorString*) {
196 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true);
197 }
198
199 void V8HeapProfilerAgentImpl::disable(ErrorString* error) {
200 stopTrackingHeapObjectsInternal();
201 if (m_state->booleanProperty(
202 HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) {
203 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
204 if (profiler) profiler->StopSamplingHeapProfiler();
205 }
206 m_isolate->GetHeapProfiler()->ClearObjectIds();
207 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false);
208 }
209
210 void V8HeapProfilerAgentImpl::takeHeapSnapshot(
211 ErrorString* errorString, const protocol::Maybe<bool>& reportProgress) {
212 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
213 if (!profiler) {
214 *errorString = "Cannot access v8 heap profiler";
215 return;
216 }
217 std::unique_ptr<HeapSnapshotProgress> progress;
218 if (reportProgress.fromMaybe(false))
219 progress = wrapUnique(new HeapSnapshotProgress(&m_frontend));
220
221 GlobalObjectNameResolver resolver(m_session);
222 const v8::HeapSnapshot* snapshot =
223 profiler->TakeHeapSnapshot(progress.get(), &resolver);
224 if (!snapshot) {
225 *errorString = "Failed to take heap snapshot";
226 return;
227 }
228 HeapSnapshotOutputStream stream(&m_frontend);
229 snapshot->Serialize(&stream);
230 const_cast<v8::HeapSnapshot*>(snapshot)->Delete();
231 }
232
233 void V8HeapProfilerAgentImpl::getObjectByHeapObjectId(
234 ErrorString* error, const String16& heapSnapshotObjectId,
235 const protocol::Maybe<String16>& objectGroup,
236 std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
237 bool ok;
238 int id = heapSnapshotObjectId.toInteger(&ok);
239 if (!ok) {
240 *error = "Invalid heap snapshot object id";
241 return;
242 }
243
244 v8::HandleScope handles(m_isolate);
245 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id);
246 if (heapObject.IsEmpty()) {
247 *error = "Object is not available";
248 return;
249 }
250
251 if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) {
252 *error = "Object is not available";
253 return;
254 }
255
256 *result = m_session->wrapObject(heapObject->CreationContext(), heapObject,
257 objectGroup.fromMaybe(""), false);
258 if (!result) *error = "Object is not available";
259 }
260
261 void V8HeapProfilerAgentImpl::addInspectedHeapObject(
262 ErrorString* errorString, const String16& inspectedHeapObjectId) {
263 bool ok;
264 int id = inspectedHeapObjectId.toInteger(&ok);
265 if (!ok) {
266 *errorString = "Invalid heap snapshot object id";
267 return;
268 }
269
270 v8::HandleScope handles(m_isolate);
271 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id);
272 if (heapObject.IsEmpty()) {
273 *errorString = "Object is not available";
274 return;
275 }
276
277 if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) {
278 *errorString = "Object is not available";
279 return;
280 }
281
282 m_session->addInspectedObject(wrapUnique(new InspectableHeapObject(id)));
283 }
284
285 void V8HeapProfilerAgentImpl::getHeapObjectId(ErrorString* errorString,
286 const String16& objectId,
287 String16* heapSnapshotObjectId) {
288 v8::HandleScope handles(m_isolate);
289 v8::Local<v8::Value> value;
290 v8::Local<v8::Context> context;
291 if (!m_session->unwrapObject(errorString, objectId, &value, &context,
292 nullptr) ||
293 value->IsUndefined())
294 return;
295
296 v8::SnapshotObjectId id = m_isolate->GetHeapProfiler()->GetObjectId(value);
297 *heapSnapshotObjectId = String16::fromInteger(id);
298 }
299
300 void V8HeapProfilerAgentImpl::requestHeapStatsUpdate() {
301 HeapStatsStream stream(&m_frontend);
302 v8::SnapshotObjectId lastSeenObjectId =
303 m_isolate->GetHeapProfiler()->GetHeapStats(&stream);
304 m_frontend.lastSeenObjectId(
305 lastSeenObjectId, m_session->inspector()->client()->currentTimeMS());
306 }
307
308 // static
309 void V8HeapProfilerAgentImpl::onTimer(void* data) {
310 reinterpret_cast<V8HeapProfilerAgentImpl*>(data)->requestHeapStatsUpdate();
311 }
312
313 void V8HeapProfilerAgentImpl::startTrackingHeapObjectsInternal(
314 bool trackAllocations) {
315 m_isolate->GetHeapProfiler()->StartTrackingHeapObjects(trackAllocations);
316 if (!m_hasTimer) {
317 m_hasTimer = true;
318 m_session->inspector()->client()->startRepeatingTimer(
319 0.05, &V8HeapProfilerAgentImpl::onTimer, reinterpret_cast<void*>(this));
320 }
321 }
322
323 void V8HeapProfilerAgentImpl::stopTrackingHeapObjectsInternal() {
324 if (m_hasTimer) {
325 m_session->inspector()->client()->cancelTimer(
326 reinterpret_cast<void*>(this));
327 m_hasTimer = false;
328 }
329 m_isolate->GetHeapProfiler()->StopTrackingHeapObjects();
330 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled,
331 false);
332 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, false);
333 }
334
335 void V8HeapProfilerAgentImpl::startSampling(
336 ErrorString* errorString, const Maybe<double>& samplingInterval) {
337 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
338 if (!profiler) {
339 *errorString = "Cannot access v8 heap profiler";
340 return;
341 }
342 const unsigned defaultSamplingInterval = 1 << 15;
343 double samplingIntervalValue =
344 samplingInterval.fromMaybe(defaultSamplingInterval);
345 m_state->setDouble(HeapProfilerAgentState::samplingHeapProfilerInterval,
346 samplingIntervalValue);
347 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled,
348 true);
349 profiler->StartSamplingHeapProfiler(
350 static_cast<uint64_t>(samplingIntervalValue), 128,
351 v8::HeapProfiler::kSamplingForceGC);
352 }
353
354 namespace {
355 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode>
356 buildSampingHeapProfileNode(const v8::AllocationProfile::Node* node) {
357 auto children = protocol::Array<
358 protocol::HeapProfiler::SamplingHeapProfileNode>::create();
359 for (const auto* child : node->children)
360 children->addItem(buildSampingHeapProfileNode(child));
361 size_t selfSize = 0;
362 for (const auto& allocation : node->allocations)
363 selfSize += allocation.size * allocation.count;
364 std::unique_ptr<protocol::Runtime::CallFrame> callFrame =
365 protocol::Runtime::CallFrame::create()
366 .setFunctionName(toProtocolString(node->name))
367 .setScriptId(String16::fromInteger(node->script_id))
368 .setUrl(toProtocolString(node->script_name))
369 .setLineNumber(node->line_number - 1)
370 .setColumnNumber(node->column_number - 1)
371 .build();
372 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> result =
373 protocol::HeapProfiler::SamplingHeapProfileNode::create()
374 .setCallFrame(std::move(callFrame))
375 .setSelfSize(selfSize)
376 .setChildren(std::move(children))
377 .build();
378 return result;
379 }
380 } // namespace
381
382 void V8HeapProfilerAgentImpl::stopSampling(
383 ErrorString* errorString,
384 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) {
385 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
386 if (!profiler) {
387 *errorString = "Cannot access v8 heap profiler";
388 return;
389 }
390 v8::HandleScope scope(
391 m_isolate); // Allocation profile contains Local handles.
392 std::unique_ptr<v8::AllocationProfile> v8Profile(
393 profiler->GetAllocationProfile());
394 profiler->StopSamplingHeapProfiler();
395 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled,
396 false);
397 if (!v8Profile) {
398 *errorString = "Cannot access v8 sampled heap profile.";
399 return;
400 }
401 v8::AllocationProfile::Node* root = v8Profile->GetRootNode();
402 *profile = protocol::HeapProfiler::SamplingHeapProfile::create()
403 .setHead(buildSampingHeapProfileNode(root))
404 .build();
405 }
406
407 } // namespace v8_inspector
OLDNEW
« no previous file with comments | « src/inspector/V8HeapProfilerAgentImpl.h ('k') | src/inspector/V8InjectedScriptHost.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698