| 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 |