InspectorHeapProfilerAgent.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Copyright (C) 2013 Google Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above
  11. * copyright notice, this list of conditions and the following disclaimer
  12. * in the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Google Inc. nor the names of its
  15. * contributors may be used to endorse or promote products derived from
  16. * this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "config.h"
  31. #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
  32. #include "InspectorHeapProfilerAgent.h"
  33. #include "InjectedScript.h"
  34. #include "InjectedScriptHost.h"
  35. #include "InspectorState.h"
  36. #include "InstrumentingAgents.h"
  37. #include "ScriptProfiler.h"
  38. namespace WebCore {
  39. namespace HeapProfilerAgentState {
  40. static const char profileHeadersRequested[] = "profileHeadersRequested";
  41. }
  42. static const char* const UserInitiatedProfileNameHeap = "org.webkit.profiles.user-initiated";
  43. PassOwnPtr<InspectorHeapProfilerAgent> InspectorHeapProfilerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager)
  44. {
  45. return adoptPtr(new InspectorHeapProfilerAgent(instrumentingAgents, inspectorState, injectedScriptManager));
  46. }
  47. InspectorHeapProfilerAgent::InspectorHeapProfilerAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* inspectorState, InjectedScriptManager* injectedScriptManager)
  48. : InspectorBaseAgent<InspectorHeapProfilerAgent>("HeapProfiler", instrumentingAgents, inspectorState)
  49. , m_injectedScriptManager(injectedScriptManager)
  50. , m_frontend(0)
  51. , m_nextUserInitiatedHeapSnapshotNumber(1)
  52. {
  53. m_instrumentingAgents->setInspectorHeapProfilerAgent(this);
  54. }
  55. InspectorHeapProfilerAgent::~InspectorHeapProfilerAgent()
  56. {
  57. m_instrumentingAgents->setInspectorHeapProfilerAgent(0);
  58. }
  59. void InspectorHeapProfilerAgent::resetState()
  60. {
  61. m_snapshots.clear();
  62. m_nextUserInitiatedHeapSnapshotNumber = 1;
  63. resetFrontendProfiles();
  64. m_injectedScriptManager->injectedScriptHost()->clearInspectedObjects();
  65. }
  66. void InspectorHeapProfilerAgent::resetFrontendProfiles()
  67. {
  68. if (!m_frontend)
  69. return;
  70. if (!m_state->getBoolean(HeapProfilerAgentState::profileHeadersRequested))
  71. return;
  72. if (m_snapshots.isEmpty())
  73. m_frontend->resetProfiles();
  74. }
  75. void InspectorHeapProfilerAgent::setFrontend(InspectorFrontend* frontend)
  76. {
  77. m_frontend = frontend->heapprofiler();
  78. }
  79. void InspectorHeapProfilerAgent::clearFrontend()
  80. {
  81. m_state->setBoolean(HeapProfilerAgentState::profileHeadersRequested, false);
  82. m_frontend = 0;
  83. }
  84. void InspectorHeapProfilerAgent::restore()
  85. {
  86. resetFrontendProfiles();
  87. }
  88. void InspectorHeapProfilerAgent::collectGarbage(WebCore::ErrorString*)
  89. {
  90. ScriptProfiler::collectGarbage();
  91. }
  92. PassRefPtr<TypeBuilder::HeapProfiler::ProfileHeader> InspectorHeapProfilerAgent::createSnapshotHeader(const ScriptHeapSnapshot& snapshot)
  93. {
  94. RefPtr<TypeBuilder::HeapProfiler::ProfileHeader> header = TypeBuilder::HeapProfiler::ProfileHeader::create()
  95. .setUid(snapshot.uid())
  96. .setTitle(snapshot.title());
  97. header->setMaxJSObjectId(snapshot.maxSnapshotJSObjectId());
  98. return header.release();
  99. }
  100. void InspectorHeapProfilerAgent::hasHeapProfiler(ErrorString*, bool* result)
  101. {
  102. *result = ScriptProfiler::hasHeapProfiler();
  103. }
  104. void InspectorHeapProfilerAgent::getProfileHeaders(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::HeapProfiler::ProfileHeader> >& headers)
  105. {
  106. m_state->setBoolean(HeapProfilerAgentState::profileHeadersRequested, true);
  107. headers = TypeBuilder::Array<TypeBuilder::HeapProfiler::ProfileHeader>::create();
  108. IdToHeapSnapshotMap::iterator snapshotsEnd = m_snapshots.end();
  109. for (IdToHeapSnapshotMap::iterator it = m_snapshots.begin(); it != snapshotsEnd; ++it)
  110. headers->addItem(createSnapshotHeader(*it->value));
  111. }
  112. void InspectorHeapProfilerAgent::getHeapSnapshot(ErrorString* errorString, int rawUid)
  113. {
  114. class OutputStream : public ScriptHeapSnapshot::OutputStream {
  115. public:
  116. OutputStream(InspectorFrontend::HeapProfiler* frontend, unsigned uid)
  117. : m_frontend(frontend), m_uid(uid) { }
  118. void Write(const String& chunk) { m_frontend->addHeapSnapshotChunk(m_uid, chunk); }
  119. void Close() { m_frontend->finishHeapSnapshot(m_uid); }
  120. private:
  121. InspectorFrontend::HeapProfiler* m_frontend;
  122. int m_uid;
  123. };
  124. unsigned uid = static_cast<unsigned>(rawUid);
  125. IdToHeapSnapshotMap::iterator it = m_snapshots.find(uid);
  126. if (it == m_snapshots.end()) {
  127. *errorString = "Profile wasn't found";
  128. return;
  129. }
  130. RefPtr<ScriptHeapSnapshot> snapshot = it->value;
  131. if (m_frontend) {
  132. OutputStream stream(m_frontend, uid);
  133. snapshot->writeJSON(&stream);
  134. }
  135. }
  136. void InspectorHeapProfilerAgent::removeProfile(ErrorString*, int rawUid)
  137. {
  138. unsigned uid = static_cast<unsigned>(rawUid);
  139. if (m_snapshots.contains(uid))
  140. m_snapshots.remove(uid);
  141. }
  142. void InspectorHeapProfilerAgent::takeHeapSnapshot(ErrorString*, const bool* reportProgress)
  143. {
  144. class HeapSnapshotProgress: public ScriptProfiler::HeapSnapshotProgress {
  145. public:
  146. explicit HeapSnapshotProgress(InspectorFrontend::HeapProfiler* frontend)
  147. : m_frontend(frontend) { }
  148. void Start(int totalWork)
  149. {
  150. m_totalWork = totalWork;
  151. }
  152. void Worked(int workDone)
  153. {
  154. if (m_frontend)
  155. m_frontend->reportHeapSnapshotProgress(workDone, m_totalWork);
  156. }
  157. void Done() { }
  158. bool isCanceled() { return false; }
  159. private:
  160. InspectorFrontend::HeapProfiler* m_frontend;
  161. int m_totalWork;
  162. };
  163. String title = makeString(UserInitiatedProfileNameHeap, '.', String::number(m_nextUserInitiatedHeapSnapshotNumber));
  164. ++m_nextUserInitiatedHeapSnapshotNumber;
  165. HeapSnapshotProgress progress(reportProgress && *reportProgress ? m_frontend : 0);
  166. RefPtr<ScriptHeapSnapshot> snapshot = ScriptProfiler::takeHeapSnapshot(title, &progress);
  167. if (snapshot) {
  168. m_snapshots.add(snapshot->uid(), snapshot);
  169. if (m_frontend)
  170. m_frontend->addProfileHeader(createSnapshotHeader(*snapshot));
  171. }
  172. }
  173. void InspectorHeapProfilerAgent::getObjectByHeapObjectId(ErrorString* error, const String& heapSnapshotObjectId, const String* objectGroup, RefPtr<TypeBuilder::Runtime::RemoteObject>& result)
  174. {
  175. bool ok;
  176. unsigned id = heapSnapshotObjectId.toUInt(&ok);
  177. if (!ok) {
  178. *error = "Invalid heap snapshot object id";
  179. return;
  180. }
  181. ScriptObject heapObject = ScriptProfiler::objectByHeapObjectId(id);
  182. if (heapObject.hasNoValue()) {
  183. *error = "Object is not available";
  184. return;
  185. }
  186. InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(heapObject.scriptState());
  187. if (injectedScript.hasNoValue()) {
  188. *error = "Object is not available. Inspected context is gone";
  189. return;
  190. }
  191. result = injectedScript.wrapObject(heapObject, objectGroup ? *objectGroup : "");
  192. if (!result)
  193. *error = "Failed to wrap object";
  194. }
  195. void InspectorHeapProfilerAgent::getHeapObjectId(ErrorString* errorString, const String& objectId, String* heapSnapshotObjectId)
  196. {
  197. InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
  198. if (injectedScript.hasNoValue()) {
  199. *errorString = "Inspected context has gone";
  200. return;
  201. }
  202. ScriptValue value = injectedScript.findObjectById(objectId);
  203. if (value.hasNoValue() || value.isUndefined()) {
  204. *errorString = "Object with given id not found";
  205. return;
  206. }
  207. unsigned id = ScriptProfiler::getHeapObjectId(value);
  208. *heapSnapshotObjectId = String::number(id);
  209. }
  210. } // namespace WebCore
  211. #endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)