1e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block/*
2e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * Copyright (C) 2010 Apple Inc. All rights reserved.
3e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * Copyright (C) 2010 Google Inc. All rights reserved.
4e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *
5e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * Redistribution and use in source and binary forms, with or without
6e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * modification, are permitted provided that the following conditions
7e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * are met:
8e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *
9e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * 1.  Redistributions of source code must retain the above copyright
10e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *     notice, this list of conditions and the following disclaimer.
11e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * 2.  Redistributions in binary form must reproduce the above copyright
12e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *     notice, this list of conditions and the following disclaimer in the
13e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *     documentation and/or other materials provided with the distribution.
14e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *     its contributors may be used to endorse or promote products derived
16e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *     from this software without specific prior written permission.
17e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block *
18e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block */
29e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
30e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "config.h"
31e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "InspectorProfilerAgent.h"
32e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
334576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
34e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
35e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "Console.h"
3665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "InspectorConsoleAgent.h"
37e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "InspectorFrontend.h"
382bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "InspectorState.h"
39e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "InspectorValues.h"
4081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#include "InstrumentingAgents.h"
41e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "KURL.h"
42e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "Page.h"
432bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "PageScriptDebugServer.h"
442bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "ScriptController.h"
455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#include "ScriptHeapSnapshot.h"
46e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "ScriptProfile.h"
47e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "ScriptProfiler.h"
48e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include <wtf/OwnPtr.h>
49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include <wtf/text/StringConcatenate.h>
50e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
51e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#if USE(JSC)
52e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#include "JSDOMWindow.h"
53e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#endif
54e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
55e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blocknamespace WebCore {
56e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
572bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace ProfilerAgentState {
582bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic const char userInitiatedProfiling[] = "userInitiatedProfiling";
592bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic const char profilerEnabled[] = "profilerEnabled";
602bde8e466a4451c7319e3a072d118917957d6554Steve Block}
612bde8e466a4451c7319e3a072d118917957d6554Steve Block
62e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic const char* const UserInitiatedProfileName = "org.webkit.profiles.user-initiated";
63e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic const char* const CPUProfileType = "CPU";
645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenstatic const char* const HeapProfileType = "HEAP";
65e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
662bde8e466a4451c7319e3a072d118917957d6554Steve BlockPassOwnPtr<InspectorProfilerAgent> InspectorProfilerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, Page* inspectedPage, InspectorState* inspectorState)
67e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
682bde8e466a4451c7319e3a072d118917957d6554Steve Block    return adoptPtr(new InspectorProfilerAgent(instrumentingAgents, consoleAgent, inspectedPage, inspectorState));
69e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
70e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
712bde8e466a4451c7319e3a072d118917957d6554Steve BlockInspectorProfilerAgent::InspectorProfilerAgent(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, Page* inspectedPage, InspectorState* inspectorState)
7281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    : m_instrumentingAgents(instrumentingAgents)
7381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_consoleAgent(consoleAgent)
7481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_inspectedPage(inspectedPage)
752bde8e466a4451c7319e3a072d118917957d6554Steve Block    , m_inspectorState(inspectorState)
76e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    , m_frontend(0)
772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    , m_enabled(false)
78e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    , m_recordingUserInitiatedProfile(false)
79e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    , m_currentUserInitiatedProfileNumber(-1)
80e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    , m_nextUserInitiatedProfileNumber(1)
815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    , m_nextUserInitiatedHeapSnapshotNumber(1)
82e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
8381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    m_instrumentingAgents->setInspectorProfilerAgent(this);
84e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
85e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
86e8b154fd68f9b33be40a3590e58347f353835f5cSteve BlockInspectorProfilerAgent::~InspectorProfilerAgent()
87e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
8881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    m_instrumentingAgents->setInspectorProfilerAgent(0);
89e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
90e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
91e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid InspectorProfilerAgent::addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL)
92e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
93e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    RefPtr<ScriptProfile> profile = prpProfile;
94e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_profiles.add(profile->uid(), profile);
95e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_frontend)
96e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_frontend->addProfileHeader(createProfileHeader(*profile));
97e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    addProfileFinishedMessageToConsole(profile, lineNumber, sourceURL);
98e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
99e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
100e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid InspectorProfilerAgent::addProfileFinishedMessageToConsole(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL)
101e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
102ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (!m_frontend)
103ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        return;
104e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    RefPtr<ScriptProfile> profile = prpProfile;
105e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    String title = profile->title();
106a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    String message = makeString("Profile \"webkit-profile://", CPUProfileType, '/', encodeWithURLEscapeSequences(title), '#', String::number(profile->uid()), "\" finished.");
10781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    m_consoleAgent->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
108e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
109e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
110e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid InspectorProfilerAgent::addStartProfilingMessageToConsole(const String& title, unsigned lineNumber, const String& sourceURL)
111e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
112ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (!m_frontend)
113ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        return;
11428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    String message = makeString("Profile \"webkit-profile://", CPUProfileType, '/', encodeWithURLEscapeSequences(title), "#0\" started.");
11581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    m_consoleAgent->addMessageToConsole(JSMessageSource, LogMessageType, LogMessageLevel, message, lineNumber, sourceURL);
116e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
117e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
1182bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid InspectorProfilerAgent::collectGarbage(WebCore::ErrorString*)
1192bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1202bde8e466a4451c7319e3a072d118917957d6554Steve Block    ScriptProfiler::collectGarbage();
1212bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1222bde8e466a4451c7319e3a072d118917957d6554Steve Block
123e8b154fd68f9b33be40a3590e58347f353835f5cSteve BlockPassRefPtr<InspectorObject> InspectorProfilerAgent::createProfileHeader(const ScriptProfile& profile)
124e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
125e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    RefPtr<InspectorObject> header = InspectorObject::create();
126e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    header->setString("title", profile.title());
127e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    header->setNumber("uid", profile.uid());
128e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    header->setString("typeId", String(CPUProfileType));
129e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    return header;
130e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
131e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
1325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenPassRefPtr<InspectorObject> InspectorProfilerAgent::createSnapshotHeader(const ScriptHeapSnapshot& snapshot)
1335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
1345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    RefPtr<InspectorObject> header = InspectorObject::create();
1355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    header->setString("title", snapshot.title());
1365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    header->setNumber("uid", snapshot.uid());
1375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    header->setString("typeId", String(HeapProfileType));
1385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    return header;
1395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1412bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid InspectorProfilerAgent::enable(ErrorString*)
1422bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1432bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (enabled())
1442bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
1452bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_inspectorState->setBoolean(ProfilerAgentState::profilerEnabled, true);
1462bde8e466a4451c7319e3a072d118917957d6554Steve Block    enable(false);
1472bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1482bde8e466a4451c7319e3a072d118917957d6554Steve Block
1492bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid InspectorProfilerAgent::disable(ErrorString*)
1502bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1512bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_inspectorState->setBoolean(ProfilerAgentState::profilerEnabled, false);
1522bde8e466a4451c7319e3a072d118917957d6554Steve Block    disable();
1532bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1542bde8e466a4451c7319e3a072d118917957d6554Steve Block
155e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid InspectorProfilerAgent::disable()
156e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
157e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!m_enabled)
158e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
159e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_enabled = false;
1602bde8e466a4451c7319e3a072d118917957d6554Steve Block    PageScriptDebugServer::shared().recompileAllJSFunctionsSoon();
161e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_frontend)
162e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_frontend->profilerWasDisabled();
163e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
164e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
165e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid InspectorProfilerAgent::enable(bool skipRecompile)
166e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
167e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_enabled)
168e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        return;
169e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_enabled = true;
170e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!skipRecompile)
1712bde8e466a4451c7319e3a072d118917957d6554Steve Block        PageScriptDebugServer::shared().recompileAllJSFunctionsSoon();
172e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_frontend)
173e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_frontend->profilerWasEnabled();
174e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
175e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
176e8b154fd68f9b33be40a3590e58347f353835f5cSteve BlockString InspectorProfilerAgent::getCurrentUserInitiatedProfileName(bool incrementProfileNumber)
177e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
178e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (incrementProfileNumber)
179e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_currentUserInitiatedProfileNumber = m_nextUserInitiatedProfileNumber++;
180e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
181a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return makeString(UserInitiatedProfileName, '.', String::number(m_currentUserInitiatedProfileNumber));
182e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
183e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
18481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid InspectorProfilerAgent::getProfileHeaders(ErrorString*, RefPtr<InspectorArray>* headers)
185e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
186e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    ProfilesMap::iterator profilesEnd = m_profiles.end();
187e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    for (ProfilesMap::iterator it = m_profiles.begin(); it != profilesEnd; ++it)
188e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        (*headers)->pushObject(createProfileHeader(*it->second));
1895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    HeapSnapshotsMap::iterator snapshotsEnd = m_snapshots.end();
1905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    for (HeapSnapshotsMap::iterator it = m_snapshots.begin(); it != snapshotsEnd; ++it)
1915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        (*headers)->pushObject(createSnapshotHeader(*it->second));
1925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
194f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochnamespace {
195f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
196f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochclass OutputStream : public ScriptHeapSnapshot::OutputStream {
197f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochpublic:
1982bde8e466a4451c7319e3a072d118917957d6554Steve Block    OutputStream(InspectorFrontend::Profiler* frontend, unsigned uid)
199f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        : m_frontend(frontend), m_uid(uid) { }
200f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    void Write(const String& chunk) { m_frontend->addHeapSnapshotChunk(m_uid, chunk); }
201f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    void Close() { m_frontend->finishHeapSnapshot(m_uid); }
202f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochprivate:
20381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    InspectorFrontend::Profiler* m_frontend;
2042bde8e466a4451c7319e3a072d118917957d6554Steve Block    int m_uid;
205f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch};
206f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
207f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} // namespace
208f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
20981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid InspectorProfilerAgent::getProfile(ErrorString*, const String& type, unsigned uid, RefPtr<InspectorObject>* profileObject)
2105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
2115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (type == CPUProfileType) {
2125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        ProfilesMap::iterator it = m_profiles.find(uid);
2135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if (it != m_profiles.end()) {
2145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            *profileObject = createProfileHeader(*it->second);
2155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            (*profileObject)->setObject("head", it->second->buildInspectorObjectForHead());
2165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
2175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    } else if (type == HeapProfileType) {
2185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        HeapSnapshotsMap::iterator it = m_snapshots.find(uid);
2195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if (it != m_snapshots.end()) {
220f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            RefPtr<ScriptHeapSnapshot> snapshot = it->second;
221f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            *profileObject = createSnapshotHeader(*snapshot);
222f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            if (m_frontend) {
223f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                OutputStream stream(m_frontend, uid);
224f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                snapshot->writeJSON(&stream);
225f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            }
2265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
227e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
228e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
229e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
23081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid InspectorProfilerAgent::removeProfile(ErrorString*, const String& type, unsigned uid)
231e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
2325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (type == CPUProfileType) {
2335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if (m_profiles.contains(uid))
2345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            m_profiles.remove(uid);
2355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    } else if (type == HeapProfileType) {
2365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if (m_snapshots.contains(uid))
2375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            m_snapshots.remove(uid);
2385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
239e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
240e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
241e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid InspectorProfilerAgent::resetState()
242e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
2432bde8e466a4451c7319e3a072d118917957d6554Steve Block    stopUserInitiatedProfiling();
244e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_profiles.clear();
2455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    m_snapshots.clear();
246e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_currentUserInitiatedProfileNumber = 1;
247e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_nextUserInitiatedProfileNumber = 1;
2485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    m_nextUserInitiatedHeapSnapshotNumber = 1;
249ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    resetFrontendProfiles();
250ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch}
251ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
252ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochvoid InspectorProfilerAgent::resetFrontendProfiles()
253ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch{
2542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (m_frontend
2552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        && m_profiles.begin() == m_profiles.end()
2562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        && m_snapshots.begin() == m_snapshots.end())
257f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_frontend->resetProfiles();
258e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
259e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
2602bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid InspectorProfilerAgent::setFrontend(InspectorFrontend* frontend)
2612bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2622bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_frontend = frontend->profiler();
2632bde8e466a4451c7319e3a072d118917957d6554Steve Block    restoreEnablement();
2642bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2652bde8e466a4451c7319e3a072d118917957d6554Steve Block
2662bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid InspectorProfilerAgent::clearFrontend()
2672bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2682bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_frontend = 0;
2692bde8e466a4451c7319e3a072d118917957d6554Steve Block    stopUserInitiatedProfiling();
2702bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2712bde8e466a4451c7319e3a072d118917957d6554Steve Block
2722bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid InspectorProfilerAgent::restore()
2732bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2742bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Need to restore enablement state here as in setFrontend m_inspectorState wasn't loaded yet.
2752bde8e466a4451c7319e3a072d118917957d6554Steve Block    restoreEnablement();
2762bde8e466a4451c7319e3a072d118917957d6554Steve Block
2772bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Revisit this.
2782bde8e466a4451c7319e3a072d118917957d6554Steve Block    resetFrontendProfiles();
2792bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (m_inspectorState->getBoolean(ProfilerAgentState::userInitiatedProfiling))
2802bde8e466a4451c7319e3a072d118917957d6554Steve Block        startUserInitiatedProfiling();
2812bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2822bde8e466a4451c7319e3a072d118917957d6554Steve Block
2832bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid InspectorProfilerAgent::restoreEnablement()
2842bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2852bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (m_inspectorState->getBoolean(ProfilerAgentState::profilerEnabled)) {
2862bde8e466a4451c7319e3a072d118917957d6554Steve Block        ErrorString error;
2872bde8e466a4451c7319e3a072d118917957d6554Steve Block        enable(&error);
2882bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
2892bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2902bde8e466a4451c7319e3a072d118917957d6554Steve Block
291e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid InspectorProfilerAgent::startUserInitiatedProfiling()
292e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
29328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (m_recordingUserInitiatedProfile)
29428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        return;
295e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (!enabled()) {
2962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        enable(true);
2972bde8e466a4451c7319e3a072d118917957d6554Steve Block        PageScriptDebugServer::shared().recompileAllJSFunctions(0);
298e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
299e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_recordingUserInitiatedProfile = true;
300e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    String title = getCurrentUserInitiatedProfileName(true);
301e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#if USE(JSC)
30281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    JSC::ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame(), debuggerWorld())->globalExec();
303e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#else
304e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    ScriptState* scriptState = 0;
305e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#endif
306e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    ScriptProfiler::start(scriptState, title);
307e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    addStartProfilingMessageToConsole(title, 0, String());
308e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    toggleRecordButton(true);
3092bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_inspectorState->setBoolean(ProfilerAgentState::userInitiatedProfiling, true);
310e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
311e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
31228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhuvoid InspectorProfilerAgent::stopUserInitiatedProfiling(bool ignoreProfile)
313e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
31428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (!m_recordingUserInitiatedProfile)
31528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        return;
316e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    m_recordingUserInitiatedProfile = false;
317e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    String title = getCurrentUserInitiatedProfileName();
318e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#if USE(JSC)
31981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    JSC::ExecState* scriptState = toJSDOMWindow(m_inspectedPage->mainFrame(), debuggerWorld())->globalExec();
320e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#else
321e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // Use null script state to avoid filtering by context security token.
322e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    // All functions from all iframes should be visible from Inspector UI.
323e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    ScriptState* scriptState = 0;
324e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#endif
325e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    RefPtr<ScriptProfile> profile = ScriptProfiler::stop(scriptState, title);
32628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (profile) {
32728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        if (!ignoreProfile)
32828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu            addProfile(profile, 0, String());
32928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        else
33028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu            addProfileFinishedMessageToConsole(profile, 0, String());
33128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    }
332e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    toggleRecordButton(false);
3332bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_inspectorState->setBoolean(ProfilerAgentState::userInitiatedProfiling, false);
334e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
335e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
3362fc2651226baac27029e38c9d6ef883fa32084dbSteve Blocknamespace {
3372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3382fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockclass HeapSnapshotProgress: public ScriptProfiler::HeapSnapshotProgress {
3392fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockpublic:
34081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    explicit HeapSnapshotProgress(InspectorFrontend::Profiler* frontend)
3412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        : m_frontend(frontend) { }
3422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    void Start(int totalWork)
3432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    {
3442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        m_totalWork = totalWork;
3452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
3462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    void Worked(int workDone)
3472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    {
3482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (m_frontend)
3492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            m_frontend->reportHeapSnapshotProgress(workDone, m_totalWork);
3502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
3512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    void Done() { }
3522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    bool isCanceled() { return false; }
3532fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockprivate:
35481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    InspectorFrontend::Profiler* m_frontend;
3552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int m_totalWork;
3562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block};
3572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
3582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block};
3592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
36081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid InspectorProfilerAgent::takeHeapSnapshot(ErrorString*, bool detailed)
3615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
362a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    String title = makeString(UserInitiatedProfileName, '.', String::number(m_nextUserInitiatedHeapSnapshotNumber));
363a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ++m_nextUserInitiatedHeapSnapshotNumber;
364a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
3652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    HeapSnapshotProgress progress(m_frontend);
3662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RefPtr<ScriptHeapSnapshot> snapshot = ScriptProfiler::takeHeapSnapshot(title, detailed ? &progress : 0);
3675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (snapshot) {
3685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        m_snapshots.add(snapshot->uid(), snapshot);
3695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if (m_frontend)
3705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            m_frontend->addProfileHeader(createSnapshotHeader(*snapshot));
3715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
3725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
3735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
374e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockvoid InspectorProfilerAgent::toggleRecordButton(bool isProfiling)
375e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
376e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if (m_frontend)
377e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        m_frontend->setRecordingProfile(isProfiling);
378e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
379e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
380e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block} // namespace WebCore
381e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
3824576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang#endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
383