diff --git a/third_party/WebKit/Source/core/inspector/InspectorHeapProfilerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorHeapProfilerAgent.cpp index 67513c2086f29..59f89e6f72b84 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorHeapProfilerAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorHeapProfilerAgent.cpp @@ -53,6 +53,18 @@ class InspectorHeapProfilerAgent::HeapStatsUpdateTask final { Timer m_timer; }; +class InspectorHeapProfilerAgent::HeapXDKUpdateTask final { +public: + explicit HeapXDKUpdateTask(V8HeapProfilerAgent*); + void startTimer(float sav); + void resetTimer() { m_timer.stop(); } + void onTimer(Timer*); + +private: + V8HeapProfilerAgent* m_heapProfilerAgent; + Timer m_timer; +}; + InspectorHeapProfilerAgent::HeapStatsUpdateTask::HeapStatsUpdateTask(V8HeapProfilerAgent* heapProfilerAgent) : m_heapProfilerAgent(heapProfilerAgent) , m_timer(this, &HeapStatsUpdateTask::onTimer) @@ -231,4 +243,46 @@ void InspectorHeapProfilerAgent::stopSampling(ErrorString* errorString, OwnPtr

stopSampling(errorString, profile); } +InspectorHeapProfilerAgent::HeapXDKUpdateTask::HeapXDKUpdateTask(V8HeapProfilerAgent* heapProfilerAgent) + : m_heapProfilerAgent(heapProfilerAgent) + , m_timer(this, &HeapXDKUpdateTask::onTimer) +{ +} + +void InspectorHeapProfilerAgent::HeapXDKUpdateTask::onTimer(Timer*) +{ + // The timer is stopped on m_heapProfilerAgent destruction, + // so this method will never be called after m_heapProfilerAgent has been destroyed. + m_heapProfilerAgent->requestHeapXDKUpdate(); +} + +void InspectorHeapProfilerAgent::HeapXDKUpdateTask::startTimer(float sav) +{ + ASSERT(!m_timer.isActive()); + m_timer.startRepeating(sav, BLINK_FROM_HERE); +} + +void InspectorHeapProfilerAgent::startTrackingHeapXDK(ErrorString* error, const protocol::Maybe& depth, const protocol::Maybe& sav, const protocol::Maybe& retentions) +{ + if (m_heapXDKUpdateTask) + return; + + m_v8HeapProfilerAgent->startTrackingHeapXDK(error, depth, sav, retentions); + float savTimer = (float) sav.fromMaybe(1000) / 1000.; + m_heapXDKUpdateTask = adoptPtr(new HeapXDKUpdateTask(m_v8HeapProfilerAgent.get())); + m_heapXDKUpdateTask->startTimer(savTimer); +} + +void InspectorHeapProfilerAgent::stopTrackingHeapXDK(ErrorString* error, OwnPtr* profile) +{ + if (!m_heapXDKUpdateTask) { + *error = "Heap object tracking is not started."; + return; + } + + m_v8HeapProfilerAgent->stopTrackingHeapXDK(error, profile); + m_heapXDKUpdateTask->resetTimer(); + m_heapXDKUpdateTask.clear(); +} + } // namespace blink diff --git a/third_party/WebKit/Source/core/inspector/InspectorHeapProfilerAgent.h b/third_party/WebKit/Source/core/inspector/InspectorHeapProfilerAgent.h index 095c435bc086d..91e96f499d5e3 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorHeapProfilerAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorHeapProfilerAgent.h @@ -37,6 +37,7 @@ #include "wtf/Noncopyable.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" +#include namespace v8 { class Isolate; @@ -73,9 +74,13 @@ class CORE_EXPORT InspectorHeapProfilerAgent final : public InspectorBaseAgent*) override; + void startTrackingHeapXDK(ErrorString*, const Maybe& stack_depth, const Maybe& sav, const Maybe& retentions) override; + void stopTrackingHeapXDK(ErrorString*, OwnPtr*) override; private: class HeapStatsUpdateTask; + class HeapXDKStream; + class HeapXDKUpdateTask; InspectorHeapProfilerAgent(v8::Isolate*, V8RuntimeAgent*); @@ -85,6 +90,7 @@ class CORE_EXPORT InspectorHeapProfilerAgent final : public InspectorBaseAgent m_v8HeapProfilerAgent; OwnPtr m_heapStatsUpdateTask; + OwnPtr m_heapXDKUpdateTask; v8::Isolate* m_isolate; }; diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/HeapProfilerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/HeapProfilerModel.js index 8b689694e95f0..5e54ffeb5f4d1 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/HeapProfilerModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/HeapProfilerModel.js @@ -16,7 +16,8 @@ WebInspector.HeapProfilerModel.Events = { LastSeenObjectId: "LastSeenObjectId", AddHeapSnapshotChunk: "AddHeapSnapshotChunk", ReportHeapSnapshotProgress: "ReportHeapSnapshotProgress", - ResetProfiles: "ResetProfiles" + ResetProfiles: "ResetProfiles", + HeapXDKUpdate: "HeapXDKUpdate" } WebInspector.HeapProfilerModel.prototype = { @@ -70,6 +71,14 @@ WebInspector.HeapProfilerModel.prototype = { this.dispatchEventToListeners(WebInspector.HeapProfilerModel.Events.ResetProfiles); }, + /** + * @param {string} message + */ + heapXDKUpdate: function (message) + { + this.dispatchEventToListeners(WebInspector.HeapProfilerModel.Events.HeapXDKUpdate, message); + }, + __proto__: WebInspector.SDKModel.prototype } @@ -129,5 +138,14 @@ WebInspector.HeapProfilerDispatcher.prototype = { resetProfiles: function() { this._heapProfilerModel.resetProfiles(); + }, + + /** + * @override + * @param {string} message + */ + heapXDKUpdate: function(message) + { + this._heapProfilerModel.heapXDKUpdate(message); } } \ No newline at end of file diff --git a/third_party/WebKit/Source/devtools/protocol.json b/third_party/WebKit/Source/devtools/protocol.json index 658784236072b..dbb806bc0a1c1 100644 --- a/third_party/WebKit/Source/devtools/protocol.json +++ b/third_party/WebKit/Source/devtools/protocol.json @@ -4016,6 +4016,7 @@ { "name": "columnNumber", "type": "integer", "description": "1-based column number of the function start position." }, { "name": "hitCount", "type": "integer", "description": "Number of samples where this node was on top of the call stack." }, { "name": "callUID", "type": "number", "description": "Call UID." }, + { "name": "stackEntryLine", "type": "integer", "description": "Hit line for entry in stack." }, { "name": "children", "type": "array", "items": { "$ref": "CPUProfileNode" }, "description": "Child nodes." }, { "name": "deoptReason", "type": "string", "description": "The reason of being not optimized. The function may be deoptimized or marked as don't optimize."}, { "name": "id", "type": "integer", "description": "Unique id of the node." }, @@ -4120,6 +4121,19 @@ "properties": [ { "name": "head", "$ref": "SamplingHeapProfileNode" } ] + }, + { + "id": "HeapEventXDK", + "type": "object", + "description": "", + "properties": [ + { "name": "duration", "type": "integer" }, + { "name": "symbols", "type": "string" }, + { "name": "frames", "type": "string" }, + { "name": "types", "type": "string" }, + { "name": "chunks", "type": "string" }, + { "name": "retentions", "type": "string" } + ] } ], "commands": [ @@ -4142,6 +4156,20 @@ ] }, + { + "name": "startTrackingHeapXDK", + "parameters": [ + { "name": "stack_depth", "type": "integer", "optional": true }, + { "name": "sav", "type": "integer", "optional": true }, + { "name": "retentions", "type": "boolean", "optional": true } + ] + }, + { + "name": "stopTrackingHeapXDK", + "returns": [ + { "name": "profileXDK", "$ref": "HeapEventXDK", "description": "Recorded profile." } + ] + }, { "name": "takeHeapSnapshot", "parameters": [ @@ -4219,6 +4247,16 @@ "parameters": [ { "name": "statsUpdate", "type": "array", "items": { "type": "integer" }, "description": "An array of triplets. Each triplet describes a fragment. The first integer is the fragment index, the second integer is a total count of objects for the fragment, the third integer is a total size of the objects for the fragment."} ] + }, + { + "name": "heapXDKUpdate", + "parameters": [ + { "name": "symbols", "type": "string" }, + { "name": "frames", "type": "string" }, + { "name": "types", "type": "string" }, + { "name": "chunks", "type": "string" }, + { "name": "retentions", "type": "string" } + ] } ] }, diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp index 86265c82b541e..06fcbaeeb01a2 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp @@ -341,4 +341,113 @@ void V8HeapProfilerAgentImpl::stopSampling(ErrorString* errorString, OwnPtrheapXDKUpdate(String(symbols, symbolsSize), String(frames, framesSize), String(types, typesSize), String(chunks, chunksSize), String(retentions, retentionSize)); + return kContinue; + } + +private: + protocol::Frontend::HeapProfiler* m_frontend; +}; + +static PassOwnPtr createHeapProfileXDK(const HeapProfileXDK& heapProfileXDK) +{ + OwnPtr profile = protocol::HeapProfiler::HeapEventXDK::create() + .setDuration(heapProfileXDK.getDuration()) + .setSymbols(heapProfileXDK.getSymbols()) + .setFrames(heapProfileXDK.getFrames()) + .setTypes(heapProfileXDK.getTypes()) + .setChunks(heapProfileXDK.getChunks()) + .setRetentions(heapProfileXDK.getRetentions()).build(); + return profile.release(); +} + +void V8HeapProfilerAgentImpl::startTrackingHeapXDK(ErrorString* error, const protocol::Maybe& depth, const protocol::Maybe& sav, const protocol::Maybe& retentions) +{ + v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); + if (!profiler) { + *error = "Cannot access v8 heap profiler"; + return; + } + + m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true); + int stackDepth = depth.fromMaybe(8); + bool needRetentions = retentions.fromMaybe(false); + profiler->StartTrackingHeapObjectsXDK(stackDepth, needRetentions); +} + +void V8HeapProfilerAgentImpl::stopTrackingHeapXDK(ErrorString* error, OwnPtr* profile) +{ + v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); + if (!profiler) { + *error = "Cannot access v8 heap profiler"; + return; + } + + OwnPtr heapProfileXDK = HeapProfileXDK::create( + profiler->StopTrackingHeapObjectsXDK(), m_isolate); + *profile = createHeapProfileXDK(*heapProfileXDK); + m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, false); +} + +void V8HeapProfilerAgentImpl::requestHeapXDKUpdate() +{ + if (!m_frontend) + return; + HeapXDKStream heapXDKStream(m_frontend); + m_isolate->GetHeapProfiler()->GetHeapXDKStats( + &heapXDKStream); +} + +String HeapProfileXDK::getSymbols() const +{ + v8::HandleScope handleScope(m_isolate); + return String(m_event->getSymbols()); +} + +String HeapProfileXDK::getFrames() const +{ + v8::HandleScope handleScope(m_isolate); + return String(m_event->getFrames()); +} + +String HeapProfileXDK::getTypes() const +{ + v8::HandleScope handleScope(m_isolate); + return String(m_event->getTypes()); +} + +String HeapProfileXDK::getChunks() const +{ + v8::HandleScope handleScope(m_isolate); + return String(m_event->getChunks()); +} + +int HeapProfileXDK::getDuration() const +{ + return (int)m_event->getDuration(); +} + +String HeapProfileXDK::getRetentions() const +{ + v8::HandleScope handleScope(m_isolate); + return String(m_event->getRetentions()); +} + } // namespace blink diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.h index 366951b19d7c8..2b223f327ceaf 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.h +++ b/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.h @@ -8,6 +8,7 @@ #include "platform/v8_inspector/public/V8HeapProfilerAgent.h" #include "wtf/Forward.h" #include "wtf/Noncopyable.h" +#include namespace blink { @@ -17,6 +18,31 @@ typedef String ErrorString; using protocol::Maybe; +class HeapProfileXDK final { +public: + static PassOwnPtr create(v8::HeapEventXDK* event, v8::Isolate* isolate) + { + return adoptPtr(new HeapProfileXDK(event, isolate)); + } + + String getSymbols() const; + String getFrames() const; + String getTypes() const; + String getChunks() const; + String getRetentions() const; + int getDuration() const; + +private: + HeapProfileXDK(v8::HeapEventXDK* event, v8::Isolate* isolate) + : m_event(event), + m_isolate(isolate) + { + } + + v8::HeapEventXDK* m_event; + v8::Isolate* m_isolate; +}; + class V8HeapProfilerAgentImpl : public V8HeapProfilerAgent { WTF_MAKE_NONCOPYABLE(V8HeapProfilerAgentImpl); public: @@ -42,10 +68,14 @@ class V8HeapProfilerAgentImpl : public V8HeapProfilerAgent { void addInspectedHeapObject(ErrorString*, const String& inspectedHeapObjectId) override; void getHeapObjectId(ErrorString*, const String& objectId, String* heapSnapshotObjectId) override; + void startTrackingHeapXDK(ErrorString*, const Maybe& depth, const Maybe& sav, const Maybe& retentions) override; + void stopTrackingHeapXDK(ErrorString*, OwnPtr*) override; + void startSampling(ErrorString*) override; void stopSampling(ErrorString*, OwnPtr*) override; void requestHeapStatsUpdate() override; + void requestHeapXDKUpdate() override; private: void startTrackingHeapObjectsInternal(bool trackAllocations); diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.cpp index 4a2315151973b..fb3231030808a 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8ProfilerAgentImpl.cpp @@ -60,6 +60,7 @@ PassOwnPtr buildInspectorObjectFor(v8::Isola .setColumnNumber(node->GetColumnNumber()) .setHitCount(node->GetHitCount()) .setCallUID(node->GetCallUid()) + .setStackEntryLine(node->GetSrcLine()) .setChildren(children.release()) .setPositionTicks(positionTicks.release()) .setDeoptReason(node->GetBailoutReason()) diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8HeapProfilerAgent.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8HeapProfilerAgent.h index 479da255b1c92..3aafa7f3fc124 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8HeapProfilerAgent.h +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8HeapProfilerAgent.h @@ -19,6 +19,7 @@ class PLATFORM_EXPORT V8HeapProfilerAgent : public protocol::Dispatcher::HeapPro virtual ~V8HeapProfilerAgent() { } virtual void requestHeapStatsUpdate() = 0; + virtual void requestHeapXDKUpdate() = 0; }; } // namespace blink