Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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 "platform/v8_inspector/V8HeapProfilerAgentImpl.h" | 5 #include "platform/v8_inspector/V8HeapProfilerAgentImpl.h" |
| 6 | 6 |
| 7 #include "platform/v8_inspector/InjectedScript.h" | 7 #include "platform/v8_inspector/InjectedScript.h" |
| 8 #include "platform/v8_inspector/InjectedScriptManager.h" | 8 #include "platform/v8_inspector/InjectedScriptManager.h" |
| 9 #include "platform/v8_inspector/V8RuntimeAgentImpl.h" | 9 #include "platform/v8_inspector/V8RuntimeAgentImpl.h" |
| 10 #include "platform/v8_inspector/V8StringUtil.h" | 10 #include "platform/v8_inspector/V8StringUtil.h" |
| 11 #include "wtf/CurrentTime.h" | 11 #include "wtf/CurrentTime.h" |
| 12 #include <v8-profiler.h> | 12 #include <v8-profiler.h> |
| 13 | 13 |
| 14 namespace blink { | 14 namespace blink { |
| 15 | 15 |
| 16 namespace HeapProfilerAgentState { | 16 namespace HeapProfilerAgentState { |
| 17 static const char heapProfilerEnabled[] = "heapProfilerEnabled"; | 17 static const char heapProfilerEnabled[] = "heapProfilerEnabled"; |
| 18 static const char heapObjectsTrackingEnabled[] = "heapObjectsTrackingEnabled"; | 18 static const char heapObjectsTrackingEnabled[] = "heapObjectsTrackingEnabled"; |
| 19 static const char allocationTrackingEnabled[] = "allocationTrackingEnabled"; | 19 static const char allocationTrackingEnabled[] = "allocationTrackingEnabled"; |
| 20 static const char samplingHeapProfilerEnabled[] = "samplingHeapProfilerEnabled"; | 20 static const char samplingHeapProfilerEnabled[] = "samplingHeapProfilerEnabled"; |
| 21 } | 21 } |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 bool asBool(const bool* value) | |
| 26 { | |
| 27 return value && *value; | |
| 28 } | |
| 29 | |
| 30 class HeapSnapshotProgress final : public v8::ActivityControl { | 25 class HeapSnapshotProgress final : public v8::ActivityControl { |
| 31 public: | 26 public: |
| 32 HeapSnapshotProgress(protocol::Frontend::HeapProfiler* frontend) | 27 HeapSnapshotProgress(protocol::Frontend::HeapProfiler* frontend) |
| 33 : m_frontend(frontend) { } | 28 : m_frontend(frontend) { } |
| 34 ControlOption ReportProgressValue(int done, int total) override | 29 ControlOption ReportProgressValue(int done, int total) override |
| 35 { | 30 { |
| 36 m_frontend->reportHeapSnapshotProgress(done, total, nullptr); | 31 m_frontend->reportHeapSnapshotProgress(done, total, protocol::TypeBuilde r::OptionalValue<bool>()); |
|
dgozman
2016/02/22 23:57:36
We could use default parameters to simplify such c
| |
| 37 if (done >= total) { | 32 if (done >= total) { |
| 38 const bool finished = true; | 33 m_frontend->reportHeapSnapshotProgress(total, total, protocol::TypeB uilder::OptionalValue<bool>(true)); |
| 39 m_frontend->reportHeapSnapshotProgress(total, total, &finished); | |
| 40 } | 34 } |
| 41 m_frontend->flush(); | 35 m_frontend->flush(); |
| 42 return kContinue; | 36 return kContinue; |
| 43 } | 37 } |
| 44 private: | 38 private: |
| 45 protocol::Frontend::HeapProfiler* m_frontend; | 39 protocol::Frontend::HeapProfiler* m_frontend; |
| 46 }; | 40 }; |
| 47 | 41 |
| 48 class GlobalObjectNameResolver final : public v8::HeapProfiler::ObjectNameResolv er { | 42 class GlobalObjectNameResolver final : public v8::HeapProfiler::ObjectNameResolv er { |
| 49 public: | 43 public: |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 113 | 107 |
| 114 WriteResult WriteAsciiChunk(char* data, int size) override | 108 WriteResult WriteAsciiChunk(char* data, int size) override |
| 115 { | 109 { |
| 116 ASSERT(false); | 110 ASSERT(false); |
| 117 return kAbort; | 111 return kAbort; |
| 118 } | 112 } |
| 119 | 113 |
| 120 WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* updateData, int count) override | 114 WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* updateData, int count) override |
| 121 { | 115 { |
| 122 ASSERT(count > 0); | 116 ASSERT(count > 0); |
| 123 RefPtr<protocol::TypeBuilder::Array<int>> statsDiff = protocol::TypeBuil der::Array<int>::create(); | 117 OwnPtr<protocol::TypeBuilder::Array<int>> statsDiff = protocol::TypeBuil der::Array<int>::create(); |
| 124 for (int i = 0; i < count; ++i) { | 118 for (int i = 0; i < count; ++i) { |
| 125 statsDiff->addItem(updateData[i].index); | 119 statsDiff->addItem(updateData[i].index); |
| 126 statsDiff->addItem(updateData[i].count); | 120 statsDiff->addItem(updateData[i].count); |
| 127 statsDiff->addItem(updateData[i].size); | 121 statsDiff->addItem(updateData[i].size); |
| 128 } | 122 } |
| 129 m_frontend->heapStatsUpdate(statsDiff.release()); | 123 m_frontend->heapStatsUpdate(statsDiff.release()); |
| 130 return kContinue; | 124 return kContinue; |
| 131 } | 125 } |
| 132 | 126 |
| 133 private: | 127 private: |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 ErrorString error; | 163 ErrorString error; |
| 170 startSampling(&error); | 164 startSampling(&error); |
| 171 } | 165 } |
| 172 } | 166 } |
| 173 | 167 |
| 174 void V8HeapProfilerAgentImpl::collectGarbage(ErrorString*) | 168 void V8HeapProfilerAgentImpl::collectGarbage(ErrorString*) |
| 175 { | 169 { |
| 176 m_isolate->LowMemoryNotification(); | 170 m_isolate->LowMemoryNotification(); |
| 177 } | 171 } |
| 178 | 172 |
| 179 void V8HeapProfilerAgentImpl::startTrackingHeapObjects(ErrorString*, const bool* trackAllocations) | 173 void V8HeapProfilerAgentImpl::startTrackingHeapObjects(ErrorString*, const proto col::TypeBuilder::OptionalValue<bool>& trackAllocations) |
| 180 { | 174 { |
| 181 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true ); | 175 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true ); |
| 182 bool allocationTrackingEnabled = asBool(trackAllocations); | 176 bool allocationTrackingEnabled = trackAllocations.get(false); |
| 183 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, alloc ationTrackingEnabled); | 177 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, alloc ationTrackingEnabled); |
| 184 startTrackingHeapObjectsInternal(allocationTrackingEnabled); | 178 startTrackingHeapObjectsInternal(allocationTrackingEnabled); |
| 185 } | 179 } |
| 186 | 180 |
| 187 void V8HeapProfilerAgentImpl::stopTrackingHeapObjects(ErrorString* error, const bool* reportProgress) | 181 void V8HeapProfilerAgentImpl::stopTrackingHeapObjects(ErrorString* error, const protocol::TypeBuilder::OptionalValue<bool>& reportProgress) |
| 188 { | 182 { |
| 189 requestHeapStatsUpdate(); | 183 requestHeapStatsUpdate(); |
| 190 takeHeapSnapshot(error, reportProgress); | 184 takeHeapSnapshot(error, reportProgress); |
| 191 stopTrackingHeapObjectsInternal(); | 185 stopTrackingHeapObjectsInternal(); |
| 192 } | 186 } |
| 193 | 187 |
| 194 void V8HeapProfilerAgentImpl::enable(ErrorString*) | 188 void V8HeapProfilerAgentImpl::enable(ErrorString*) |
| 195 { | 189 { |
| 196 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true); | 190 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true); |
| 197 } | 191 } |
| 198 | 192 |
| 199 void V8HeapProfilerAgentImpl::disable(ErrorString* error) | 193 void V8HeapProfilerAgentImpl::disable(ErrorString* error) |
| 200 { | 194 { |
| 201 stopTrackingHeapObjectsInternal(); | 195 stopTrackingHeapObjectsInternal(); |
| 202 if (m_state->booleanProperty(HeapProfilerAgentState::samplingHeapProfilerEna bled, false)) { | 196 if (m_state->booleanProperty(HeapProfilerAgentState::samplingHeapProfilerEna bled, false)) { |
| 203 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); | 197 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); |
| 204 if (profiler) | 198 if (profiler) |
| 205 profiler->StopSamplingHeapProfiler(); | 199 profiler->StopSamplingHeapProfiler(); |
| 206 } | 200 } |
| 207 m_isolate->GetHeapProfiler()->ClearObjectIds(); | 201 m_isolate->GetHeapProfiler()->ClearObjectIds(); |
| 208 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false); | 202 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false); |
| 209 } | 203 } |
| 210 | 204 |
| 211 void V8HeapProfilerAgentImpl::takeHeapSnapshot(ErrorString* errorString, const b ool* reportProgress) | 205 void V8HeapProfilerAgentImpl::takeHeapSnapshot(ErrorString* errorString, const p rotocol::TypeBuilder::OptionalValue<bool>& reportProgress) |
| 212 { | 206 { |
| 213 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); | 207 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); |
| 214 if (!profiler) { | 208 if (!profiler) { |
| 215 *errorString = "Cannot access v8 heap profiler"; | 209 *errorString = "Cannot access v8 heap profiler"; |
| 216 return; | 210 return; |
| 217 } | 211 } |
| 218 OwnPtr<HeapSnapshotProgress> progress; | 212 OwnPtr<HeapSnapshotProgress> progress; |
| 219 if (asBool(reportProgress)) | 213 if (reportProgress.get(false)) |
| 220 progress = adoptPtr(new HeapSnapshotProgress(m_frontend)); | 214 progress = adoptPtr(new HeapSnapshotProgress(m_frontend)); |
| 221 | 215 |
| 222 GlobalObjectNameResolver resolver(static_cast<V8RuntimeAgentImpl*>(m_runtime Agent)); | 216 GlobalObjectNameResolver resolver(static_cast<V8RuntimeAgentImpl*>(m_runtime Agent)); |
| 223 const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(progress.get() , &resolver); | 217 const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(progress.get() , &resolver); |
| 224 if (!snapshot) { | 218 if (!snapshot) { |
| 225 *errorString = "Failed to take heap snapshot"; | 219 *errorString = "Failed to take heap snapshot"; |
| 226 return; | 220 return; |
| 227 } | 221 } |
| 228 HeapSnapshotOutputStream stream(m_frontend); | 222 HeapSnapshotOutputStream stream(m_frontend); |
| 229 snapshot->Serialize(&stream); | 223 snapshot->Serialize(&stream); |
| 230 const_cast<v8::HeapSnapshot*>(snapshot)->Delete(); | 224 const_cast<v8::HeapSnapshot*>(snapshot)->Delete(); |
| 231 } | 225 } |
| 232 | 226 |
| 233 void V8HeapProfilerAgentImpl::getObjectByHeapObjectId(ErrorString* error, const String& heapSnapshotObjectId, const String* objectGroup, RefPtr<protocol::TypeBu ilder::Runtime::RemoteObject>& result) | 227 void V8HeapProfilerAgentImpl::getObjectByHeapObjectId(ErrorString* error, const String& heapSnapshotObjectId, const protocol::TypeBuilder::OptionalValue<String> & objectGroup, OwnPtr<protocol::TypeBuilder::Runtime::RemoteObject>* result) |
| 234 { | 228 { |
| 235 bool ok; | 229 bool ok; |
| 236 unsigned id = heapSnapshotObjectId.toUInt(&ok); | 230 unsigned id = heapSnapshotObjectId.toUInt(&ok); |
| 237 if (!ok) { | 231 if (!ok) { |
| 238 *error = "Invalid heap snapshot object id"; | 232 *error = "Invalid heap snapshot object id"; |
| 239 return; | 233 return; |
| 240 } | 234 } |
| 241 | 235 |
| 242 v8::HandleScope handles(m_isolate); | 236 v8::HandleScope handles(m_isolate); |
| 243 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id); | 237 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id); |
| 244 if (heapObject.IsEmpty()) { | 238 if (heapObject.IsEmpty()) { |
| 245 *error = "Object is not available"; | 239 *error = "Object is not available"; |
| 246 return; | 240 return; |
| 247 } | 241 } |
| 248 result = m_runtimeAgent->wrapObject(heapObject->CreationContext(), heapObjec t, objectGroup ? *objectGroup : ""); | 242 *result = m_runtimeAgent->wrapObject(heapObject->CreationContext(), heapObje ct, objectGroup.get("")); |
| 249 if (!result) | 243 if (!result) |
| 250 *error = "Object is not available"; | 244 *error = "Object is not available"; |
| 251 } | 245 } |
| 252 | 246 |
| 253 void V8HeapProfilerAgentImpl::addInspectedHeapObject(ErrorString* errorString, c onst String& inspectedHeapObjectId) | 247 void V8HeapProfilerAgentImpl::addInspectedHeapObject(ErrorString* errorString, c onst String& inspectedHeapObjectId) |
| 254 { | 248 { |
| 255 bool ok; | 249 bool ok; |
| 256 unsigned id = inspectedHeapObjectId.toUInt(&ok); | 250 unsigned id = inspectedHeapObjectId.toUInt(&ok); |
| 257 if (!ok) { | 251 if (!ok) { |
| 258 *errorString = "Invalid heap snapshot object id"; | 252 *errorString = "Invalid heap snapshot object id"; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); | 294 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); |
| 301 if (!profiler) { | 295 if (!profiler) { |
| 302 *errorString = "Cannot access v8 heap profiler"; | 296 *errorString = "Cannot access v8 heap profiler"; |
| 303 return; | 297 return; |
| 304 } | 298 } |
| 305 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, tru e); | 299 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, tru e); |
| 306 profiler->StartSamplingHeapProfiler(); | 300 profiler->StartSamplingHeapProfiler(); |
| 307 } | 301 } |
| 308 | 302 |
| 309 namespace { | 303 namespace { |
| 310 PassRefPtr<protocol::TypeBuilder::HeapProfiler::SamplingHeapProfileNode> buildSa mpingHeapProfileNode(const v8::AllocationProfile::Node* node) | 304 PassOwnPtr<protocol::TypeBuilder::HeapProfiler::SamplingHeapProfileNode> buildSa mpingHeapProfileNode(const v8::AllocationProfile::Node* node) |
| 311 { | 305 { |
| 312 auto children = protocol::TypeBuilder::Array<protocol::TypeBuilder::HeapProf iler::SamplingHeapProfileNode>::create(); | 306 auto children = protocol::TypeBuilder::Array<protocol::TypeBuilder::HeapProf iler::SamplingHeapProfileNode>::create(); |
| 313 for (const auto* child : node->children) | 307 for (const auto* child : node->children) |
| 314 children->addItem(buildSampingHeapProfileNode(child)); | 308 children->addItem(buildSampingHeapProfileNode(child)); |
| 315 size_t totalSize = 0; | 309 size_t totalSize = 0; |
| 316 for (const auto& allocation : node->allocations) | 310 for (const auto& allocation : node->allocations) |
| 317 totalSize += allocation.size * allocation.count; | 311 totalSize += allocation.size * allocation.count; |
| 318 RefPtr<protocol::TypeBuilder::HeapProfiler::SamplingHeapProfileNode> result = protocol::TypeBuilder::HeapProfiler::SamplingHeapProfileNode::create() | 312 OwnPtr<protocol::TypeBuilder::HeapProfiler::SamplingHeapProfileNode> result = protocol::TypeBuilder::HeapProfiler::SamplingHeapProfileNode::create() |
| 319 .setFunctionName(toWTFString(node->name)) | 313 .setFunctionName(toWTFString(node->name)) |
| 320 .setScriptId(String::number(node->script_id)) | 314 .setScriptId(String::number(node->script_id)) |
| 321 .setUrl(toWTFString(node->script_name)) | 315 .setUrl(toWTFString(node->script_name)) |
| 322 .setLineNumber(node->line_number) | 316 .setLineNumber(node->line_number) |
| 323 .setColumnNumber(node->column_number) | 317 .setColumnNumber(node->column_number) |
| 324 .setTotalSize(totalSize) | 318 .setTotalSize(totalSize) |
| 325 .setChildren(children); | 319 .setChildren(children).build(); |
| 326 return result.release(); | 320 return result.release(); |
| 327 } | 321 } |
| 328 } // namespace | 322 } // namespace |
| 329 | 323 |
| 330 void V8HeapProfilerAgentImpl::stopSampling(ErrorString* errorString, RefPtr<prot ocol::TypeBuilder::HeapProfiler::SamplingHeapProfile>& profile) | 324 void V8HeapProfilerAgentImpl::stopSampling(ErrorString* errorString, OwnPtr<prot ocol::TypeBuilder::HeapProfiler::SamplingHeapProfile>* profile) |
| 331 { | 325 { |
| 332 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); | 326 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); |
| 333 if (!profiler) { | 327 if (!profiler) { |
| 334 *errorString = "Cannot access v8 heap profiler"; | 328 *errorString = "Cannot access v8 heap profiler"; |
| 335 return; | 329 return; |
| 336 } | 330 } |
| 337 v8::HandleScope scope(m_isolate); // Allocation profile contains Local handl es. | 331 v8::HandleScope scope(m_isolate); // Allocation profile contains Local handl es. |
| 338 OwnPtr<v8::AllocationProfile> v8Profile = adoptPtr(profiler->GetAllocationPr ofile()); | 332 OwnPtr<v8::AllocationProfile> v8Profile = adoptPtr(profiler->GetAllocationPr ofile()); |
| 339 profiler->StopSamplingHeapProfiler(); | 333 profiler->StopSamplingHeapProfiler(); |
| 340 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, fal se); | 334 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, fal se); |
| 341 if (!v8Profile) { | 335 if (!v8Profile) { |
| 342 *errorString = "Cannot access v8 sampled heap profile."; | 336 *errorString = "Cannot access v8 sampled heap profile."; |
| 343 return; | 337 return; |
| 344 } | 338 } |
| 345 v8::AllocationProfile::Node* root = v8Profile->GetRootNode(); | 339 v8::AllocationProfile::Node* root = v8Profile->GetRootNode(); |
| 346 profile = protocol::TypeBuilder::HeapProfiler::SamplingHeapProfile::create() | 340 *profile = protocol::TypeBuilder::HeapProfiler::SamplingHeapProfile::create( ) |
| 347 .setHead(buildSampingHeapProfileNode(root)); | 341 .setHead(buildSampingHeapProfileNode(root)).build(); |
| 348 } | 342 } |
| 349 | 343 |
| 350 } // namespace blink | 344 } // namespace blink |
| OLD | NEW |