2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "InspectorProfilerAgent.h"
35 #include "InspectorValues.h"
36 #include "LegacyProfiler.h"
38 #include "ScriptDebugServer.h"
39 #include "ScriptObject.h"
40 #include <wtf/CurrentTime.h>
41 #include <wtf/text/StringConcatenate.h>
45 static const char* const UserInitiatedProfileName
= "org.webkit.profiles.user-initiated";
46 static const char* const CPUProfileType
= "CPU";
48 InspectorProfilerAgent::InspectorProfilerAgent()
49 : InspectorAgentBase(ASCIILiteral("Profiler"))
50 , m_scriptDebugServer(nullptr)
52 , m_profileHeadersRequested(false)
53 , m_recordingProfileCount(0)
54 , m_nextUserInitiatedProfileNumber(1)
58 InspectorProfilerAgent::~InspectorProfilerAgent()
62 void InspectorProfilerAgent::didCreateFrontendAndBackend(InspectorFrontendChannel
* frontendChannel
, InspectorBackendDispatcher
* backendDispatcher
)
64 m_frontendDispatcher
= std::make_unique
<InspectorProfilerFrontendDispatcher
>(frontendChannel
);
65 m_backendDispatcher
= InspectorProfilerBackendDispatcher::create(backendDispatcher
, this);
68 void InspectorProfilerAgent::willDestroyFrontendAndBackend(InspectorDisconnectReason reason
)
70 m_frontendDispatcher
= nullptr;
71 m_backendDispatcher
.clear();
75 disable(reason
== InspectorDisconnectReason::InspectedTargetDestroyed
? SkipRecompile
: Recompile
);
78 void InspectorProfilerAgent::addProfile(PassRefPtr
<JSC::Profile
> prpProfile
)
80 RefPtr
<JSC::Profile
> profile
= prpProfile
;
81 m_profiles
.add(profile
->uid(), profile
);
83 if (m_frontendDispatcher
&& m_profileHeadersRequested
)
84 m_frontendDispatcher
->addProfileHeader(createProfileHeader(*profile
));
87 PassRefPtr
<TypeBuilder::Profiler::ProfileHeader
> InspectorProfilerAgent::createProfileHeader(const JSC::Profile
& profile
)
89 return TypeBuilder::Profiler::ProfileHeader::create()
90 .setTypeId(TypeBuilder::Profiler::ProfileHeader::TypeId::CPU
)
91 .setUid(profile
.uid())
92 .setTitle(profile
.title())
96 void InspectorProfilerAgent::enable(ErrorString
*)
101 void InspectorProfilerAgent::disable(ErrorString
*)
106 void InspectorProfilerAgent::enable(ShouldRecompile shouldRecompile
)
113 if (shouldRecompile
== Recompile
)
114 m_scriptDebugServer
->recompileAllJSFunctions();
117 void InspectorProfilerAgent::disable(ShouldRecompile shouldRecompile
)
123 m_profileHeadersRequested
= false;
125 if (shouldRecompile
== Recompile
)
126 m_scriptDebugServer
->recompileAllJSFunctions();
129 String
InspectorProfilerAgent::getUserInitiatedProfileName()
131 return makeString(UserInitiatedProfileName
, '.', String::number(m_nextUserInitiatedProfileNumber
++));
134 void InspectorProfilerAgent::getProfileHeaders(ErrorString
*, RefPtr
<TypeBuilder::Array
<TypeBuilder::Profiler::ProfileHeader
>>& headers
)
136 m_profileHeadersRequested
= true;
137 headers
= TypeBuilder::Array
<TypeBuilder::Profiler::ProfileHeader
>::create();
139 for (auto& profile
: m_profiles
.values())
140 headers
->addItem(createProfileHeader(*profile
.get()));
143 static PassRefPtr
<TypeBuilder::Profiler::CPUProfileNodeCall
> buildInspectorObject(const JSC::ProfileNode::Call
& call
)
145 RefPtr
<TypeBuilder::Profiler::CPUProfileNodeCall
> result
= TypeBuilder::Profiler::CPUProfileNodeCall::create()
146 .setStartTime(call
.startTime())
147 .setTotalTime(call
.totalTime());
148 return result
.release();
151 static PassRefPtr
<TypeBuilder::Profiler::CPUProfileNode
> buildInspectorObject(const JSC::ProfileNode
* node
)
153 RefPtr
<TypeBuilder::Array
<TypeBuilder::Profiler::CPUProfileNodeCall
>> calls
= TypeBuilder::Array
<TypeBuilder::Profiler::CPUProfileNodeCall
>::create();
154 for (const JSC::ProfileNode::Call
& call
: node
->calls())
155 calls
->addItem(buildInspectorObject(call
));
157 RefPtr
<TypeBuilder::Profiler::CPUProfileNode
> result
= TypeBuilder::Profiler::CPUProfileNode::create()
159 .setCalls(calls
.release());
161 if (!node
->functionName().isEmpty())
162 result
->setFunctionName(node
->functionName());
164 if (!node
->url().isEmpty()) {
165 result
->setUrl(node
->url());
166 result
->setLineNumber(node
->lineNumber());
167 result
->setColumnNumber(node
->columnNumber());
170 if (!node
->children().isEmpty()) {
171 RefPtr
<TypeBuilder::Array
<TypeBuilder::Profiler::CPUProfileNode
>> children
= TypeBuilder::Array
<TypeBuilder::Profiler::CPUProfileNode
>::create();
172 for (RefPtr
<JSC::ProfileNode
> profileNode
: node
->children())
173 children
->addItem(buildInspectorObject(profileNode
.get()));
174 result
->setChildren(children
);
177 return result
.release();
180 PassRefPtr
<TypeBuilder::Profiler::CPUProfile
> InspectorProfilerAgent::buildProfileInspectorObject(const JSC::Profile
* profile
)
182 RefPtr
<TypeBuilder::Array
<TypeBuilder::Profiler::CPUProfileNode
>> rootNodes
= TypeBuilder::Array
<TypeBuilder::Profiler::CPUProfileNode
>::create();
183 for (RefPtr
<JSC::ProfileNode
> profileNode
: profile
->head()->children())
184 rootNodes
->addItem(buildInspectorObject(profileNode
.get()));
186 RefPtr
<TypeBuilder::Profiler::CPUProfile
> result
= TypeBuilder::Profiler::CPUProfile::create()
187 .setRootNodes(rootNodes
);
189 if (profile
->idleTime())
190 result
->setIdleTime(profile
->idleTime());
192 return result
.release();
195 void InspectorProfilerAgent::getCPUProfile(ErrorString
* errorString
, int rawUid
, RefPtr
<TypeBuilder::Profiler::CPUProfile
>& profileObject
)
197 unsigned uid
= static_cast<unsigned>(rawUid
);
198 auto it
= m_profiles
.find(uid
);
199 if (it
== m_profiles
.end()) {
200 *errorString
= ASCIILiteral("Profile wasn't found");
204 profileObject
= buildProfileInspectorObject(it
->value
.get());
207 void InspectorProfilerAgent::removeProfile(ErrorString
*, const String
& type
, int rawUid
)
209 unsigned uid
= static_cast<unsigned>(rawUid
);
210 if (type
== CPUProfileType
)
211 m_profiles
.remove(uid
);
214 void InspectorProfilerAgent::reset()
219 m_nextUserInitiatedProfileNumber
= 1;
220 m_profileHeadersRequested
= false;
222 if (m_frontendDispatcher
&& m_profileHeadersRequested
)
223 m_frontendDispatcher
->resetProfiles();
226 void InspectorProfilerAgent::start(ErrorString
*)
231 void InspectorProfilerAgent::stop(ErrorString
*)
236 void InspectorProfilerAgent::setRecordingProfile(bool isProfiling
)
238 if (m_frontendDispatcher
)
239 m_frontendDispatcher
->setRecordingProfile(isProfiling
);
242 String
InspectorProfilerAgent::startProfiling(const String
&title
, JSC::ExecState
* exec
)
247 bool wasNotRecording
= !m_recordingProfileCount
;
248 ++m_recordingProfileCount
;
250 String resolvedTitle
= title
;
252 resolvedTitle
= getUserInitiatedProfileName();
255 exec
= profilingGlobalExecState();
258 JSC::LegacyProfiler::profiler()->startProfiling(exec
, resolvedTitle
);
261 setRecordingProfile(true);
263 return resolvedTitle
;
266 PassRefPtr
<JSC::Profile
> InspectorProfilerAgent::stopProfiling(const String
& title
, JSC::ExecState
* exec
)
268 if (!m_recordingProfileCount
)
271 --m_recordingProfileCount
;
274 exec
= profilingGlobalExecState();
277 RefPtr
<JSC::Profile
> profile
= JSC::LegacyProfiler::profiler()->stopProfiling(exec
, title
);
281 if (!m_recordingProfileCount
)
282 setRecordingProfile(false);
284 return profile
.release();
287 } // namespace Inspector
289 #endif // ENABLE(INSPECTOR)