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

Side by Side Diff: third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp

Issue 2295913003: [DevTools] Switch from platform/v8_inspector to v8/v8-inspector.h. (Closed)
Patch Set: rebase 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
OLDNEW
(Empty)
1 // Copyright 2016 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 "platform/v8_inspector/V8HeapProfilerAgentImpl.h"
6
7 #include "platform/v8_inspector/InjectedScript.h"
8 #include "platform/v8_inspector/StringUtil.h"
9 #include "platform/v8_inspector/V8Debugger.h"
10 #include "platform/v8_inspector/V8InspectorImpl.h"
11 #include "platform/v8_inspector/V8InspectorSessionImpl.h"
12 #include "platform/v8_inspector/protocol/Protocol.h"
13 #include "platform/v8_inspector/public/V8InspectorClient.h"
14
15 #include <v8-profiler.h>
16 #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 #if V8_MAJOR_VERSION >= 5
27 static const char samplingHeapProfilerEnabled[] = "samplingHeapProfilerEnabled";
28 static const char samplingHeapProfilerInterval[] = "samplingHeapProfilerInterval ";
29 #endif
30 }
31
32 class HeapSnapshotProgress final : public v8::ActivityControl {
33 public:
34 HeapSnapshotProgress(protocol::HeapProfiler::Frontend* frontend)
35 : m_frontend(frontend) { }
36 ControlOption ReportProgressValue(int done, int total) override
37 {
38 m_frontend->reportHeapSnapshotProgress(done, total, protocol::Maybe<bool >());
39 if (done >= total) {
40 m_frontend->reportHeapSnapshotProgress(total, total, true);
41 }
42 m_frontend->flush();
43 return kContinue;
44 }
45 private:
46 protocol::HeapProfiler::Frontend* m_frontend;
47 };
48
49 class GlobalObjectNameResolver final : public v8::HeapProfiler::ObjectNameResolv er {
50 public:
51 explicit GlobalObjectNameResolver(V8InspectorSessionImpl* session)
52 : m_offset(0), m_strings(10000), m_session(session) {}
53
54 const char* GetName(v8::Local<v8::Object> object) override
55 {
56 InspectedContext* context = m_session->inspector()->getContext(m_session ->contextGroupId(), V8Debugger::contextId(object->CreationContext()));
57 if (!context)
58 return "";
59 String16 name = context->origin();
60 size_t length = name.length();
61 if (m_offset + length + 1 >= m_strings.size())
62 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 {
87 m_frontend->addHeapSnapshotChunk(String16(data, size));
88 m_frontend->flush();
89 return kContinue;
90 }
91 private:
92 protocol::HeapProfiler::Frontend* m_frontend;
93 };
94
95 v8::Local<v8::Object> objectByHeapObjectId(v8::Isolate* isolate, int id)
96 {
97 v8::HeapProfiler* profiler = isolate->GetHeapProfiler();
98 v8::Local<v8::Value> value = profiler->FindObjectById(id);
99 if (value.IsEmpty() || !value->IsObject())
100 return v8::Local<v8::Object>();
101 return value.As<v8::Object>();
102 }
103
104 class InspectableHeapObject final : public V8InspectorSession::Inspectable {
105 public:
106 explicit InspectableHeapObject(int heapObjectId) : m_heapObjectId(heapObject Id) { }
107 v8::Local<v8::Value> get(v8::Local<v8::Context> context) override
108 {
109 return objectByHeapObjectId(context->GetIsolate(), m_heapObjectId);
110 }
111 private:
112 int m_heapObjectId;
113 };
114
115 class HeapStatsStream final : public v8::OutputStream {
116 public:
117 HeapStatsStream(protocol::HeapProfiler::Frontend* frontend)
118 : m_frontend(frontend)
119 {
120 }
121
122 void EndOfStream() override { }
123
124 WriteResult WriteAsciiChunk(char* data, int size) override
125 {
126 DCHECK(false);
127 return kAbort;
128 }
129
130 WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* updateData, int count) override
131 {
132 DCHECK_GT(count, 0);
133 std::unique_ptr<protocol::Array<int>> statsDiff = protocol::Array<int>:: create();
134 for (int i = 0; i < count; ++i) {
135 statsDiff->addItem(updateData[i].index);
136 statsDiff->addItem(updateData[i].count);
137 statsDiff->addItem(updateData[i].size);
138 }
139 m_frontend->heapStatsUpdate(std::move(statsDiff));
140 return kContinue;
141 }
142
143 private:
144 protocol::HeapProfiler::Frontend* m_frontend;
145 };
146
147 } // namespace
148
149 V8HeapProfilerAgentImpl::V8HeapProfilerAgentImpl(V8InspectorSessionImpl* session , protocol::FrontendChannel* frontendChannel, protocol::DictionaryValue* state)
150 : m_session(session)
151 , m_isolate(session->inspector()->isolate())
152 , m_frontend(frontendChannel)
153 , m_state(state)
154 , m_hasTimer(false)
155 {
156 }
157
158 V8HeapProfilerAgentImpl::~V8HeapProfilerAgentImpl()
159 {
160 }
161
162 void V8HeapProfilerAgentImpl::restore()
163 {
164 if (m_state->booleanProperty(HeapProfilerAgentState::heapProfilerEnabled, fa lse))
165 m_frontend.resetProfiles();
166 if (m_state->booleanProperty(HeapProfilerAgentState::heapObjectsTrackingEnab led, false))
167 startTrackingHeapObjectsInternal(m_state->booleanProperty(HeapProfilerAg entState::allocationTrackingEnabled, false));
168 #if V8_MAJOR_VERSION >= 5
169 if (m_state->booleanProperty(HeapProfilerAgentState::samplingHeapProfilerEna bled, false)) {
170 ErrorString error;
171 double samplingInterval = m_state->doubleProperty(HeapProfilerAgentState ::samplingHeapProfilerInterval, -1);
172 DCHECK_GE(samplingInterval, 0);
173 startSampling(&error, Maybe<double>(samplingInterval));
174 }
175 #endif
176 }
177
178 void V8HeapProfilerAgentImpl::collectGarbage(ErrorString*)
179 {
180 m_isolate->LowMemoryNotification();
181 }
182
183 void V8HeapProfilerAgentImpl::startTrackingHeapObjects(ErrorString*, const proto col::Maybe<bool>& trackAllocations)
184 {
185 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true );
186 bool allocationTrackingEnabled = trackAllocations.fromMaybe(false);
187 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, alloc ationTrackingEnabled);
188 startTrackingHeapObjectsInternal(allocationTrackingEnabled);
189 }
190
191 void V8HeapProfilerAgentImpl::stopTrackingHeapObjects(ErrorString* error, const protocol::Maybe<bool>& reportProgress)
192 {
193 requestHeapStatsUpdate();
194 takeHeapSnapshot(error, reportProgress);
195 stopTrackingHeapObjectsInternal();
196 }
197
198 void V8HeapProfilerAgentImpl::enable(ErrorString*)
199 {
200 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true);
201 }
202
203 void V8HeapProfilerAgentImpl::disable(ErrorString* error)
204 {
205 stopTrackingHeapObjectsInternal();
206 #if V8_MAJOR_VERSION >= 5
207 if (m_state->booleanProperty(HeapProfilerAgentState::samplingHeapProfilerEna bled, false)) {
208 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
209 if (profiler)
210 profiler->StopSamplingHeapProfiler();
211 }
212 #endif
213 m_isolate->GetHeapProfiler()->ClearObjectIds();
214 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false);
215 }
216
217 void V8HeapProfilerAgentImpl::takeHeapSnapshot(ErrorString* errorString, const p rotocol::Maybe<bool>& reportProgress)
218 {
219 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
220 if (!profiler) {
221 *errorString = "Cannot access v8 heap profiler";
222 return;
223 }
224 std::unique_ptr<HeapSnapshotProgress> progress;
225 if (reportProgress.fromMaybe(false))
226 progress = wrapUnique(new HeapSnapshotProgress(&m_frontend));
227
228 GlobalObjectNameResolver resolver(m_session);
229 const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(progress.get() , &resolver);
230 if (!snapshot) {
231 *errorString = "Failed to take heap snapshot";
232 return;
233 }
234 HeapSnapshotOutputStream stream(&m_frontend);
235 snapshot->Serialize(&stream);
236 const_cast<v8::HeapSnapshot*>(snapshot)->Delete();
237 }
238
239 void V8HeapProfilerAgentImpl::getObjectByHeapObjectId(ErrorString* error, const String16& heapSnapshotObjectId, const protocol::Maybe<String16>& objectGroup, st d::unique_ptr<protocol::Runtime::RemoteObject>* result)
240 {
241 bool ok;
242 int id = heapSnapshotObjectId.toInteger(&ok);
243 if (!ok) {
244 *error = "Invalid heap snapshot object id";
245 return;
246 }
247
248 v8::HandleScope handles(m_isolate);
249 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id);
250 if (heapObject.IsEmpty()) {
251 *error = "Object is not available";
252 return;
253 }
254
255 if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) {
256 *error = "Object is not available";
257 return;
258 }
259
260 *result = m_session->wrapObject(heapObject->CreationContext(), heapObject, o bjectGroup.fromMaybe(""), false);
261 if (!result)
262 *error = "Object is not available";
263 }
264
265 void V8HeapProfilerAgentImpl::addInspectedHeapObject(ErrorString* errorString, c onst String16& inspectedHeapObjectId)
266 {
267 bool ok;
268 int id = inspectedHeapObjectId.toInteger(&ok);
269 if (!ok) {
270 *errorString = "Invalid heap snapshot object id";
271 return;
272 }
273
274 v8::HandleScope handles(m_isolate);
275 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id);
276 if (heapObject.IsEmpty()) {
277 *errorString = "Object is not available";
278 return;
279 }
280
281 if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) {
282 *errorString = "Object is not available";
283 return;
284 }
285
286 m_session->addInspectedObject(wrapUnique(new InspectableHeapObject(id)));
287 }
288
289 void V8HeapProfilerAgentImpl::getHeapObjectId(ErrorString* errorString, const St ring16& objectId, String16* heapSnapshotObjectId)
290 {
291 v8::HandleScope handles(m_isolate);
292 v8::Local<v8::Value> value;
293 v8::Local<v8::Context> context;
294 if (!m_session->unwrapObject(errorString, objectId, &value, &context, nullpt r) || value->IsUndefined())
295 return;
296
297 v8::SnapshotObjectId id = m_isolate->GetHeapProfiler()->GetObjectId(value);
298 *heapSnapshotObjectId = String16::fromInteger(id);
299 }
300
301 void V8HeapProfilerAgentImpl::requestHeapStatsUpdate()
302 {
303 HeapStatsStream stream(&m_frontend);
304 v8::SnapshotObjectId lastSeenObjectId = m_isolate->GetHeapProfiler()->GetHea pStats(&stream);
305 m_frontend.lastSeenObjectId(lastSeenObjectId, m_session->inspector()->client ()->currentTimeMS());
306 }
307
308 // static
309 void V8HeapProfilerAgentImpl::onTimer(void* data)
310 {
311 reinterpret_cast<V8HeapProfilerAgentImpl*>(data)->requestHeapStatsUpdate();
312 }
313
314 void V8HeapProfilerAgentImpl::startTrackingHeapObjectsInternal(bool trackAllocat ions)
315 {
316 m_isolate->GetHeapProfiler()->StartTrackingHeapObjects(trackAllocations);
317 if (!m_hasTimer) {
318 m_hasTimer = true;
319 m_session->inspector()->client()->startRepeatingTimer(0.05, &V8HeapProfi lerAgentImpl::onTimer, reinterpret_cast<void*>(this));
320 }
321 }
322
323 void V8HeapProfilerAgentImpl::stopTrackingHeapObjectsInternal()
324 {
325 if (m_hasTimer) {
326 m_session->inspector()->client()->cancelTimer(reinterpret_cast<void*>(th is));
327 m_hasTimer = false;
328 }
329 m_isolate->GetHeapProfiler()->StopTrackingHeapObjects();
330 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, fals e);
331 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, false );
332 }
333
334 void V8HeapProfilerAgentImpl::startSampling(ErrorString* errorString, const Mayb e<double>& samplingInterval)
335 {
336 #if V8_MAJOR_VERSION >= 5
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 = samplingInterval.fromMaybe(defaultSamplingInt erval);
344 m_state->setDouble(HeapProfilerAgentState::samplingHeapProfilerInterval, sam plingIntervalValue);
345 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, tru e);
346 #if V8_MAJOR_VERSION * 1000 + V8_MINOR_VERSION >= 5002
347 profiler->StartSamplingHeapProfiler(static_cast<uint64_t>(samplingIntervalVa lue), 128, v8::HeapProfiler::kSamplingForceGC);
348 #else
349 profiler->StartSamplingHeapProfiler(static_cast<uint64_t>(samplingIntervalVa lue), 128);
350 #endif
351 #endif
352 }
353
354 #if V8_MAJOR_VERSION >= 5
355 namespace {
356 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> buildSampingHea pProfileNode(const v8::AllocationProfile::Node* node)
357 {
358 auto children = protocol::Array<protocol::HeapProfiler::SamplingHeapProfileN ode>::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 = protocol::Runtime: :CallFrame::create()
365 .setFunctionName(toProtocolString(node->name))
366 .setScriptId(String16::fromInteger(node->script_id))
367 .setUrl(toProtocolString(node->script_name))
368 .setLineNumber(node->line_number - 1)
369 .setColumnNumber(node->column_number - 1)
370 .build();
371 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> result = pr otocol::HeapProfiler::SamplingHeapProfileNode::create()
372 .setCallFrame(std::move(callFrame))
373 .setSelfSize(selfSize)
374 .setChildren(std::move(children)).build();
375 return result;
376 }
377 } // namespace
378 #endif
379
380 void V8HeapProfilerAgentImpl::stopSampling(ErrorString* errorString, std::unique _ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile)
381 {
382 #if V8_MAJOR_VERSION >= 5
383 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
384 if (!profiler) {
385 *errorString = "Cannot access v8 heap profiler";
386 return;
387 }
388 v8::HandleScope scope(m_isolate); // Allocation profile contains Local handl es.
389 std::unique_ptr<v8::AllocationProfile> v8Profile(profiler->GetAllocationProf ile());
390 profiler->StopSamplingHeapProfiler();
391 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, fal se);
392 if (!v8Profile) {
393 *errorString = "Cannot access v8 sampled heap profile.";
394 return;
395 }
396 v8::AllocationProfile::Node* root = v8Profile->GetRootNode();
397 *profile = protocol::HeapProfiler::SamplingHeapProfile::create()
398 .setHead(buildSampingHeapProfileNode(root)).build();
399 #endif
400 }
401
402 } // namespace v8_inspector
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698