2 * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "InspectorHeapAgent.h"
29 #include "HeapProfiler.h"
30 #include "InspectorEnvironment.h"
31 #include "JSCInlines.h"
33 #include <wtf/RunLoop.h>
34 #include <wtf/Stopwatch.h>
40 InspectorHeapAgent::InspectorHeapAgent(AgentContext& context)
41 : InspectorAgentBase(ASCIILiteral("Heap"))
42 , m_frontendDispatcher(std::make_unique<HeapFrontendDispatcher>(context.frontendRouter))
43 , m_backendDispatcher(HeapBackendDispatcher::create(context.backendDispatcher, this))
44 , m_environment(context.environment)
48 InspectorHeapAgent::~InspectorHeapAgent()
52 void InspectorHeapAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
56 void InspectorHeapAgent::willDestroyFrontendAndBackend(DisconnectReason)
59 stopTracking(ignored);
63 void InspectorHeapAgent::enable(ErrorString&)
70 m_environment.vm().heap.addObserver(this);
73 void InspectorHeapAgent::disable(ErrorString&)
80 m_environment.vm().heap.removeObserver(this);
85 void InspectorHeapAgent::gc(ErrorString&)
87 VM& vm = m_environment.vm();
88 JSLockHolder lock(vm);
89 sanitizeStackForVM(&vm);
90 vm.heap.collectAllGarbage();
93 void InspectorHeapAgent::snapshot(ErrorString&, double* timestamp, String* snapshotData)
95 VM& vm = m_environment.vm();
96 JSLockHolder lock(vm);
98 HeapSnapshotBuilder snapshotBuilder(vm.ensureHeapProfiler());
99 snapshotBuilder.buildSnapshot();
101 *timestamp = m_environment.executionStopwatch()->elapsedTime();
102 *snapshotData = snapshotBuilder.json([&] (const HeapSnapshotNode& node) {
103 if (Structure* structure = node.cell->structure(vm)) {
104 if (JSGlobalObject* globalObject = structure->globalObject()) {
105 if (!m_environment.canAccessInspectedScriptState(globalObject->globalExec()))
113 void InspectorHeapAgent::startTracking(ErrorString& errorString)
122 snapshot(errorString, ×tamp, &snapshotData);
124 m_frontendDispatcher->trackingStart(timestamp, snapshotData);
127 void InspectorHeapAgent::stopTracking(ErrorString& errorString)
136 snapshot(errorString, ×tamp, &snapshotData);
138 m_frontendDispatcher->trackingComplete(timestamp, snapshotData);
141 static Inspector::Protocol::Heap::GarbageCollection::Type protocolTypeForHeapOperation(HeapOperation operation)
145 return Inspector::Protocol::Heap::GarbageCollection::Type::Full;
147 return Inspector::Protocol::Heap::GarbageCollection::Type::Partial;
149 ASSERT_NOT_REACHED();
150 return Inspector::Protocol::Heap::GarbageCollection::Type::Full;
154 void InspectorHeapAgent::willGarbageCollect()
157 ASSERT(std::isnan(m_gcStartTime));
159 m_gcStartTime = m_environment.executionStopwatch()->elapsedTime();
162 void InspectorHeapAgent::didGarbageCollect(HeapOperation operation)
165 ASSERT(!std::isnan(m_gcStartTime));
167 // FIXME: Include number of bytes freed by collection.
169 double startTime = m_gcStartTime;
170 double endTime = m_environment.executionStopwatch()->elapsedTime();
172 // Dispatch the event asynchronously because this method may be
173 // called between collection and sweeping and we don't want to
174 // create unexpected JavaScript allocations that the Sweeper does
175 // not expect to encounter. JavaScript allocations could happen
176 // with WebKitLegacy's in process inspector which shares the same
177 // VM as the inspected page.
179 RunLoop::current().dispatch([this, startTime, endTime, operation]() {
180 auto collection = Inspector::Protocol::Heap::GarbageCollection::create()
181 .setType(protocolTypeForHeapOperation(operation))
182 .setStartTime(startTime)
186 m_frontendDispatcher->garbageCollected(WTFMove(collection));
192 void InspectorHeapAgent::clearHeapSnapshots()
194 if (HeapProfiler* heapProfiler = m_environment.vm().heapProfiler())
195 heapProfiler->clearSnapshots();
198 } // namespace Inspector