OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/inspector/v8-heap-profiler-agent-impl.h" | 5 #include "src/inspector/v8-heap-profiler-agent-impl.h" |
6 | 6 |
7 #include "src/inspector/injected-script.h" | 7 #include "src/inspector/injected-script.h" |
8 #include "src/inspector/protocol/Protocol.h" | 8 #include "src/inspector/protocol/Protocol.h" |
9 #include "src/inspector/string-util.h" | 9 #include "src/inspector/string-util.h" |
10 #include "src/inspector/v8-debugger.h" | 10 #include "src/inspector/v8-debugger.h" |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 void V8HeapProfilerAgentImpl::restore() { | 157 void V8HeapProfilerAgentImpl::restore() { |
158 if (m_state->booleanProperty(HeapProfilerAgentState::heapProfilerEnabled, | 158 if (m_state->booleanProperty(HeapProfilerAgentState::heapProfilerEnabled, |
159 false)) | 159 false)) |
160 m_frontend.resetProfiles(); | 160 m_frontend.resetProfiles(); |
161 if (m_state->booleanProperty( | 161 if (m_state->booleanProperty( |
162 HeapProfilerAgentState::heapObjectsTrackingEnabled, false)) | 162 HeapProfilerAgentState::heapObjectsTrackingEnabled, false)) |
163 startTrackingHeapObjectsInternal(m_state->booleanProperty( | 163 startTrackingHeapObjectsInternal(m_state->booleanProperty( |
164 HeapProfilerAgentState::allocationTrackingEnabled, false)); | 164 HeapProfilerAgentState::allocationTrackingEnabled, false)); |
165 if (m_state->booleanProperty( | 165 if (m_state->booleanProperty( |
166 HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) { | 166 HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) { |
167 ErrorString error; | |
168 double samplingInterval = m_state->doubleProperty( | 167 double samplingInterval = m_state->doubleProperty( |
169 HeapProfilerAgentState::samplingHeapProfilerInterval, -1); | 168 HeapProfilerAgentState::samplingHeapProfilerInterval, -1); |
170 DCHECK_GE(samplingInterval, 0); | 169 DCHECK_GE(samplingInterval, 0); |
171 startSampling(&error, Maybe<double>(samplingInterval)); | 170 startSampling(Maybe<double>(samplingInterval)); |
172 } | 171 } |
173 } | 172 } |
174 | 173 |
175 void V8HeapProfilerAgentImpl::collectGarbage(ErrorString*) { | 174 Response V8HeapProfilerAgentImpl::collectGarbage() { |
176 m_isolate->LowMemoryNotification(); | 175 m_isolate->LowMemoryNotification(); |
| 176 return Response::OK(); |
177 } | 177 } |
178 | 178 |
179 void V8HeapProfilerAgentImpl::startTrackingHeapObjects( | 179 Response V8HeapProfilerAgentImpl::startTrackingHeapObjects( |
180 ErrorString*, const protocol::Maybe<bool>& trackAllocations) { | 180 Maybe<bool> trackAllocations) { |
181 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true); | 181 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true); |
182 bool allocationTrackingEnabled = trackAllocations.fromMaybe(false); | 182 bool allocationTrackingEnabled = trackAllocations.fromMaybe(false); |
183 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, | 183 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, |
184 allocationTrackingEnabled); | 184 allocationTrackingEnabled); |
185 startTrackingHeapObjectsInternal(allocationTrackingEnabled); | 185 startTrackingHeapObjectsInternal(allocationTrackingEnabled); |
| 186 return Response::OK(); |
186 } | 187 } |
187 | 188 |
188 void V8HeapProfilerAgentImpl::stopTrackingHeapObjects( | 189 Response V8HeapProfilerAgentImpl::stopTrackingHeapObjects( |
189 ErrorString* error, const protocol::Maybe<bool>& reportProgress) { | 190 Maybe<bool> reportProgress) { |
190 requestHeapStatsUpdate(); | 191 requestHeapStatsUpdate(); |
191 takeHeapSnapshot(error, reportProgress); | 192 takeHeapSnapshot(std::move(reportProgress)); |
192 stopTrackingHeapObjectsInternal(); | 193 stopTrackingHeapObjectsInternal(); |
| 194 return Response::OK(); |
193 } | 195 } |
194 | 196 |
195 void V8HeapProfilerAgentImpl::enable(ErrorString*) { | 197 Response V8HeapProfilerAgentImpl::enable() { |
196 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true); | 198 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true); |
| 199 return Response::OK(); |
197 } | 200 } |
198 | 201 |
199 void V8HeapProfilerAgentImpl::disable(ErrorString* error) { | 202 Response V8HeapProfilerAgentImpl::disable() { |
200 stopTrackingHeapObjectsInternal(); | 203 stopTrackingHeapObjectsInternal(); |
201 if (m_state->booleanProperty( | 204 if (m_state->booleanProperty( |
202 HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) { | 205 HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) { |
203 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); | 206 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); |
204 if (profiler) profiler->StopSamplingHeapProfiler(); | 207 if (profiler) profiler->StopSamplingHeapProfiler(); |
205 } | 208 } |
206 m_isolate->GetHeapProfiler()->ClearObjectIds(); | 209 m_isolate->GetHeapProfiler()->ClearObjectIds(); |
207 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false); | 210 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false); |
| 211 return Response::OK(); |
208 } | 212 } |
209 | 213 |
210 void V8HeapProfilerAgentImpl::takeHeapSnapshot( | 214 Response V8HeapProfilerAgentImpl::takeHeapSnapshot(Maybe<bool> reportProgress) { |
211 ErrorString* errorString, const protocol::Maybe<bool>& reportProgress) { | |
212 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); | 215 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); |
213 if (!profiler) { | 216 if (!profiler) return Response::Error("Cannot access v8 heap profiler"); |
214 *errorString = "Cannot access v8 heap profiler"; | |
215 return; | |
216 } | |
217 std::unique_ptr<HeapSnapshotProgress> progress; | 217 std::unique_ptr<HeapSnapshotProgress> progress; |
218 if (reportProgress.fromMaybe(false)) | 218 if (reportProgress.fromMaybe(false)) |
219 progress = wrapUnique(new HeapSnapshotProgress(&m_frontend)); | 219 progress = wrapUnique(new HeapSnapshotProgress(&m_frontend)); |
220 | 220 |
221 GlobalObjectNameResolver resolver(m_session); | 221 GlobalObjectNameResolver resolver(m_session); |
222 const v8::HeapSnapshot* snapshot = | 222 const v8::HeapSnapshot* snapshot = |
223 profiler->TakeHeapSnapshot(progress.get(), &resolver); | 223 profiler->TakeHeapSnapshot(progress.get(), &resolver); |
224 if (!snapshot) { | 224 if (!snapshot) return Response::Error("Failed to take heap snapshot"); |
225 *errorString = "Failed to take heap snapshot"; | |
226 return; | |
227 } | |
228 HeapSnapshotOutputStream stream(&m_frontend); | 225 HeapSnapshotOutputStream stream(&m_frontend); |
229 snapshot->Serialize(&stream); | 226 snapshot->Serialize(&stream); |
230 const_cast<v8::HeapSnapshot*>(snapshot)->Delete(); | 227 const_cast<v8::HeapSnapshot*>(snapshot)->Delete(); |
| 228 return Response::OK(); |
231 } | 229 } |
232 | 230 |
233 void V8HeapProfilerAgentImpl::getObjectByHeapObjectId( | 231 Response V8HeapProfilerAgentImpl::getObjectByHeapObjectId( |
234 ErrorString* error, const String16& heapSnapshotObjectId, | 232 const String16& heapSnapshotObjectId, Maybe<String16> objectGroup, |
235 const protocol::Maybe<String16>& objectGroup, | |
236 std::unique_ptr<protocol::Runtime::RemoteObject>* result) { | 233 std::unique_ptr<protocol::Runtime::RemoteObject>* result) { |
237 bool ok; | 234 bool ok; |
238 int id = heapSnapshotObjectId.toInteger(&ok); | 235 int id = heapSnapshotObjectId.toInteger(&ok); |
239 if (!ok) { | 236 if (!ok) return Response::Error("Invalid heap snapshot object id"); |
240 *error = "Invalid heap snapshot object id"; | |
241 return; | |
242 } | |
243 | 237 |
244 v8::HandleScope handles(m_isolate); | 238 v8::HandleScope handles(m_isolate); |
245 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id); | 239 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id); |
246 if (heapObject.IsEmpty()) { | 240 if (heapObject.IsEmpty()) return Response::Error("Object is not available"); |
247 *error = "Object is not available"; | |
248 return; | |
249 } | |
250 | 241 |
251 if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) { | 242 if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) |
252 *error = "Object is not available"; | 243 return Response::Error("Object is not available"); |
253 return; | |
254 } | |
255 | 244 |
256 *result = m_session->wrapObject(heapObject->CreationContext(), heapObject, | 245 *result = m_session->wrapObject(heapObject->CreationContext(), heapObject, |
257 objectGroup.fromMaybe(""), false); | 246 objectGroup.fromMaybe(""), false); |
258 if (!result) *error = "Object is not available"; | 247 if (!result) return Response::Error("Object is not available"); |
| 248 return Response::OK(); |
259 } | 249 } |
260 | 250 |
261 void V8HeapProfilerAgentImpl::addInspectedHeapObject( | 251 Response V8HeapProfilerAgentImpl::addInspectedHeapObject( |
262 ErrorString* errorString, const String16& inspectedHeapObjectId) { | 252 const String16& inspectedHeapObjectId) { |
263 bool ok; | 253 bool ok; |
264 int id = inspectedHeapObjectId.toInteger(&ok); | 254 int id = inspectedHeapObjectId.toInteger(&ok); |
265 if (!ok) { | 255 if (!ok) return Response::Error("Invalid heap snapshot object id"); |
266 *errorString = "Invalid heap snapshot object id"; | |
267 return; | |
268 } | |
269 | 256 |
270 v8::HandleScope handles(m_isolate); | 257 v8::HandleScope handles(m_isolate); |
271 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id); | 258 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id); |
272 if (heapObject.IsEmpty()) { | 259 if (heapObject.IsEmpty()) return Response::Error("Object is not available"); |
273 *errorString = "Object is not available"; | |
274 return; | |
275 } | |
276 | 260 |
277 if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) { | 261 if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) |
278 *errorString = "Object is not available"; | 262 return Response::Error("Object is not available"); |
279 return; | |
280 } | |
281 | |
282 m_session->addInspectedObject(wrapUnique(new InspectableHeapObject(id))); | 263 m_session->addInspectedObject(wrapUnique(new InspectableHeapObject(id))); |
| 264 return Response::OK(); |
283 } | 265 } |
284 | 266 |
285 void V8HeapProfilerAgentImpl::getHeapObjectId(ErrorString* errorString, | 267 Response V8HeapProfilerAgentImpl::getHeapObjectId( |
286 const String16& objectId, | 268 const String16& objectId, String16* heapSnapshotObjectId) { |
287 String16* heapSnapshotObjectId) { | |
288 v8::HandleScope handles(m_isolate); | 269 v8::HandleScope handles(m_isolate); |
289 v8::Local<v8::Value> value; | 270 v8::Local<v8::Value> value; |
290 v8::Local<v8::Context> context; | 271 v8::Local<v8::Context> context; |
291 if (!m_session->unwrapObject(errorString, objectId, &value, &context, | 272 protocol::ErrorString errorString; |
| 273 if (!m_session->unwrapObject(&errorString, objectId, &value, &context, |
292 nullptr) || | 274 nullptr) || |
293 value->IsUndefined()) | 275 value->IsUndefined()) |
294 return; | 276 return Response::Error(errorString); |
295 | 277 |
296 v8::SnapshotObjectId id = m_isolate->GetHeapProfiler()->GetObjectId(value); | 278 v8::SnapshotObjectId id = m_isolate->GetHeapProfiler()->GetObjectId(value); |
297 *heapSnapshotObjectId = String16::fromInteger(static_cast<size_t>(id)); | 279 *heapSnapshotObjectId = String16::fromInteger(static_cast<size_t>(id)); |
| 280 return Response::OK(); |
298 } | 281 } |
299 | 282 |
300 void V8HeapProfilerAgentImpl::requestHeapStatsUpdate() { | 283 void V8HeapProfilerAgentImpl::requestHeapStatsUpdate() { |
301 HeapStatsStream stream(&m_frontend); | 284 HeapStatsStream stream(&m_frontend); |
302 v8::SnapshotObjectId lastSeenObjectId = | 285 v8::SnapshotObjectId lastSeenObjectId = |
303 m_isolate->GetHeapProfiler()->GetHeapStats(&stream); | 286 m_isolate->GetHeapProfiler()->GetHeapStats(&stream); |
304 m_frontend.lastSeenObjectId( | 287 m_frontend.lastSeenObjectId( |
305 lastSeenObjectId, m_session->inspector()->client()->currentTimeMS()); | 288 lastSeenObjectId, m_session->inspector()->client()->currentTimeMS()); |
306 } | 289 } |
307 | 290 |
(...skipping 17 matching lines...) Expand all Loading... |
325 m_session->inspector()->client()->cancelTimer( | 308 m_session->inspector()->client()->cancelTimer( |
326 reinterpret_cast<void*>(this)); | 309 reinterpret_cast<void*>(this)); |
327 m_hasTimer = false; | 310 m_hasTimer = false; |
328 } | 311 } |
329 m_isolate->GetHeapProfiler()->StopTrackingHeapObjects(); | 312 m_isolate->GetHeapProfiler()->StopTrackingHeapObjects(); |
330 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, | 313 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, |
331 false); | 314 false); |
332 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, false); | 315 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, false); |
333 } | 316 } |
334 | 317 |
335 void V8HeapProfilerAgentImpl::startSampling( | 318 Response V8HeapProfilerAgentImpl::startSampling( |
336 ErrorString* errorString, const Maybe<double>& samplingInterval) { | 319 Maybe<double> samplingInterval) { |
337 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); | 320 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); |
338 if (!profiler) { | 321 if (!profiler) return Response::Error("Cannot access v8 heap profiler"); |
339 *errorString = "Cannot access v8 heap profiler"; | |
340 return; | |
341 } | |
342 const unsigned defaultSamplingInterval = 1 << 15; | 322 const unsigned defaultSamplingInterval = 1 << 15; |
343 double samplingIntervalValue = | 323 double samplingIntervalValue = |
344 samplingInterval.fromMaybe(defaultSamplingInterval); | 324 samplingInterval.fromMaybe(defaultSamplingInterval); |
345 m_state->setDouble(HeapProfilerAgentState::samplingHeapProfilerInterval, | 325 m_state->setDouble(HeapProfilerAgentState::samplingHeapProfilerInterval, |
346 samplingIntervalValue); | 326 samplingIntervalValue); |
347 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, | 327 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, |
348 true); | 328 true); |
349 profiler->StartSamplingHeapProfiler( | 329 profiler->StartSamplingHeapProfiler( |
350 static_cast<uint64_t>(samplingIntervalValue), 128, | 330 static_cast<uint64_t>(samplingIntervalValue), 128, |
351 v8::HeapProfiler::kSamplingForceGC); | 331 v8::HeapProfiler::kSamplingForceGC); |
| 332 return Response::OK(); |
352 } | 333 } |
353 | 334 |
354 namespace { | 335 namespace { |
355 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> | 336 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> |
356 buildSampingHeapProfileNode(const v8::AllocationProfile::Node* node) { | 337 buildSampingHeapProfileNode(const v8::AllocationProfile::Node* node) { |
357 auto children = protocol::Array< | 338 auto children = protocol::Array< |
358 protocol::HeapProfiler::SamplingHeapProfileNode>::create(); | 339 protocol::HeapProfiler::SamplingHeapProfileNode>::create(); |
359 for (const auto* child : node->children) | 340 for (const auto* child : node->children) |
360 children->addItem(buildSampingHeapProfileNode(child)); | 341 children->addItem(buildSampingHeapProfileNode(child)); |
361 size_t selfSize = 0; | 342 size_t selfSize = 0; |
(...skipping 10 matching lines...) Expand all Loading... |
372 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> result = | 353 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> result = |
373 protocol::HeapProfiler::SamplingHeapProfileNode::create() | 354 protocol::HeapProfiler::SamplingHeapProfileNode::create() |
374 .setCallFrame(std::move(callFrame)) | 355 .setCallFrame(std::move(callFrame)) |
375 .setSelfSize(selfSize) | 356 .setSelfSize(selfSize) |
376 .setChildren(std::move(children)) | 357 .setChildren(std::move(children)) |
377 .build(); | 358 .build(); |
378 return result; | 359 return result; |
379 } | 360 } |
380 } // namespace | 361 } // namespace |
381 | 362 |
382 void V8HeapProfilerAgentImpl::stopSampling( | 363 Response V8HeapProfilerAgentImpl::stopSampling( |
383 ErrorString* errorString, | |
384 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) { | 364 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) { |
385 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); | 365 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); |
386 if (!profiler) { | 366 if (!profiler) return Response::Error("Cannot access v8 heap profiler"); |
387 *errorString = "Cannot access v8 heap profiler"; | |
388 return; | |
389 } | |
390 v8::HandleScope scope( | 367 v8::HandleScope scope( |
391 m_isolate); // Allocation profile contains Local handles. | 368 m_isolate); // Allocation profile contains Local handles. |
392 std::unique_ptr<v8::AllocationProfile> v8Profile( | 369 std::unique_ptr<v8::AllocationProfile> v8Profile( |
393 profiler->GetAllocationProfile()); | 370 profiler->GetAllocationProfile()); |
394 profiler->StopSamplingHeapProfiler(); | 371 profiler->StopSamplingHeapProfiler(); |
395 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, | 372 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, |
396 false); | 373 false); |
397 if (!v8Profile) { | 374 if (!v8Profile) |
398 *errorString = "Cannot access v8 sampled heap profile."; | 375 return Response::Error("Cannot access v8 sampled heap profile."); |
399 return; | |
400 } | |
401 v8::AllocationProfile::Node* root = v8Profile->GetRootNode(); | 376 v8::AllocationProfile::Node* root = v8Profile->GetRootNode(); |
402 *profile = protocol::HeapProfiler::SamplingHeapProfile::create() | 377 *profile = protocol::HeapProfiler::SamplingHeapProfile::create() |
403 .setHead(buildSampingHeapProfileNode(root)) | 378 .setHead(buildSampingHeapProfileNode(root)) |
404 .build(); | 379 .build(); |
| 380 return Response::OK(); |
405 } | 381 } |
406 | 382 |
407 } // namespace v8_inspector | 383 } // namespace v8_inspector |
OLD | NEW |