summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/devtools/debugger_agent.h22
-rw-r--r--webkit/glue/devtools/debugger_agent_impl.cc26
-rw-r--r--webkit/glue/devtools/debugger_agent_impl.h9
-rw-r--r--webkit/glue/devtools/js/debugger_agent.js154
-rw-r--r--webkit/glue/devtools/js/devtools.js12
-rw-r--r--webkit/glue/devtools/js/devtools_host_stub.js137
-rw-r--r--webkit/glue/devtools/js/inspector_controller_impl.js16
-rw-r--r--webkit/glue/devtools/js/profiler_agent.js191
-rw-r--r--webkit/glue/devtools/js/tests.js4
-rw-r--r--webkit/glue/devtools/profiler_agent.h31
-rw-r--r--webkit/glue/devtools/profiler_agent_impl.cc23
-rw-r--r--webkit/glue/devtools/profiler_agent_impl.h35
-rw-r--r--webkit/glue/webdevtoolsagent_impl.cc41
-rw-r--r--webkit/glue/webdevtoolsfrontend_impl.cc5
-rw-r--r--webkit/glue/webdevtoolsfrontend_impl.h2
-rw-r--r--webkit/webkit.gyp4
16 files changed, 442 insertions, 270 deletions
diff --git a/webkit/glue/devtools/debugger_agent.h b/webkit/glue/devtools/debugger_agent.h
index 9549447..6ba1a84 100644
--- a/webkit/glue/devtools/debugger_agent.h
+++ b/webkit/glue/devtools/debugger_agent.h
@@ -9,19 +9,7 @@
#define DEBUGGER_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \
/* Requests global context id of the inspected tab. */ \
- METHOD0(GetContextId) \
- \
- /* Starts profiling. */ \
- METHOD1(StartProfiling, int /* flags */) \
- \
- /* Stops profiling. */ \
- METHOD1(StopProfiling, int /* flags */) \
- \
- /* Requests current profiler state. */ \
- METHOD0(GetActiveProfilerModules) \
- \
- /* Retrieves next portion of profiler log. */ \
- METHOD0(GetNextLogLines)
+ METHOD0(GetContextId)
DEFINE_RPC_CLASS(DebuggerAgent, DEBUGGER_AGENT_STRUCT)
@@ -29,13 +17,7 @@ DEFINE_RPC_CLASS(DebuggerAgent, DEBUGGER_AGENT_STRUCT)
METHOD1(DebuggerOutput, String /* output text */) \
\
/* Pushes debugger context id into the client. */ \
- METHOD1(SetContextId, int /* context id */) \
- \
- /* Response to GetActiveProfilerModules. */ \
- METHOD1(DidGetActiveProfilerModules, int /* flags */) \
- \
- /* Response to GetNextLogLines. */ \
- METHOD1(DidGetNextLogLines, String /* log */)
+ METHOD1(SetContextId, int /* context id */)
DEFINE_RPC_CLASS(DebuggerAgentDelegate, DEBUGGER_AGENT_DELEGATE_STRUCT)
diff --git a/webkit/glue/devtools/debugger_agent_impl.cc b/webkit/glue/devtools/debugger_agent_impl.cc
index a354cde..fa0775e 100644
--- a/webkit/glue/devtools/debugger_agent_impl.cc
+++ b/webkit/glue/devtools/debugger_agent_impl.cc
@@ -44,7 +44,6 @@ DebuggerAgentImpl::DebuggerAgentImpl(
: web_view_impl_(web_view_impl),
delegate_(delegate),
webdevtools_agent_(webdevtools_agent),
- profiler_log_position_(0),
auto_continue_on_exception_(false) {
DebuggerAgentManager::DebugAttach(this);
}
@@ -57,31 +56,6 @@ void DebuggerAgentImpl::GetContextId() {
delegate_->SetContextId(webdevtools_agent_->host_id());
}
-void DebuggerAgentImpl::StartProfiling(int flags) {
- v8::HandleScope scope;
- WebCore::Frame* frame = GetPage()->mainFrame();
- ASSERT(V8Proxy::retrieve(GetPage()->mainFrame())->isContextInitialized());
- v8::Context::Scope context_scope(V8Proxy::context(frame));
- v8::V8::ResumeProfilerEx(flags);
-}
-
-void DebuggerAgentImpl::StopProfiling(int flags) {
- v8::V8::PauseProfilerEx(flags);
-}
-
-void DebuggerAgentImpl::GetActiveProfilerModules() {
- delegate_->DidGetActiveProfilerModules(v8::V8::GetActiveProfilerModules());
-}
-
-void DebuggerAgentImpl::GetNextLogLines() {
- static char buffer[65536];
- int read_size = v8::V8::GetLogLines(
- profiler_log_position_, buffer, sizeof(buffer) - 1);
- profiler_log_position_ += read_size;
- buffer[read_size] = '\0';
- delegate_->DidGetNextLogLines(buffer);
-}
-
void DebuggerAgentImpl::DebuggerOutput(const String& command) {
delegate_->DebuggerOutput(command);
webdevtools_agent_->ForceRepaint();
diff --git a/webkit/glue/devtools/debugger_agent_impl.h b/webkit/glue/devtools/debugger_agent_impl.h
index 96400f8..46aa990 100644
--- a/webkit/glue/devtools/debugger_agent_impl.h
+++ b/webkit/glue/devtools/debugger_agent_impl.h
@@ -38,14 +38,6 @@ class DebuggerAgentImpl : public DebuggerAgent {
// DebuggerAgent implementation.
virtual void GetContextId();
- virtual void StartProfiling(int flags);
-
- virtual void StopProfiling(int flags);
-
- virtual void GetActiveProfilerModules();
-
- virtual void GetNextLogLines();
-
void DebuggerOutput(const WebCore::String& out);
void set_auto_continue_on_exception(bool auto_continue) {
@@ -80,7 +72,6 @@ class DebuggerAgentImpl : public DebuggerAgent {
WebKit::WebViewImpl* web_view_impl_;
DebuggerAgentDelegate* delegate_;
WebDevToolsAgentImpl* webdevtools_agent_;
- int profiler_log_position_;
bool auto_continue_on_exception_;
};
diff --git a/webkit/glue/devtools/js/debugger_agent.js b/webkit/glue/devtools/js/debugger_agent.js
index 4a83551..407bc8b 100644
--- a/webkit/glue/devtools/js/debugger_agent.js
+++ b/webkit/glue/devtools/js/debugger_agent.js
@@ -17,10 +17,6 @@ devtools.DebuggerAgent = function() {
goog.bind(this.handleDebuggerOutput_, this);
RemoteDebuggerAgent.SetContextId =
goog.bind(this.setContextId_, this);
- RemoteDebuggerAgent.DidGetActiveProfilerModules =
- goog.bind(this.didGetActiveProfilerModules_, this);
- RemoteDebuggerAgent.DidGetNextLogLines =
- goog.bind(this.didGetNextLogLines_, this);
/**
* Id of the inspected page global context. It is used for filtering scripts.
@@ -90,31 +86,6 @@ devtools.DebuggerAgent = function() {
this.pendingBacktraceResponseHandler_ = null;
/**
- * Active profiler modules flags.
- * @type {number}
- */
- this.activeProfilerModules_ =
- devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE;
-
- /**
- * Interval for polling profiler state.
- * @type {number}
- */
- this.getActiveProfilerModulesInterval_ = null;
-
- /**
- * Whether log contents retrieval must be forced next time.
- * @type {boolean}
- */
- this.forceGetLogLines_ = false;
-
- /**
- * Profiler processor instance.
- * @type {devtools.profiler.Processor}
- */
- this.profilerProcessor_ = new devtools.profiler.Processor();
-
- /**
* Container of all breakpoints set using resource URL. These breakpoints
* survive page reload. Breakpoints set by script id(for scripts that don't
* have URLs) are stored in ScriptInfo objects.
@@ -145,19 +116,6 @@ devtools.DebuggerAgent.ScopeType = {
/**
- * A copy of enum from include/v8.h
- * @enum {number}
- */
-devtools.DebuggerAgent.ProfilerModules = {
- PROFILER_MODULE_NONE: 0,
- PROFILER_MODULE_CPU: 1,
- PROFILER_MODULE_HEAP_STATS: 1 << 1,
- PROFILER_MODULE_JS_CONSTRUCTORS: 1 << 2,
- PROFILER_MODULE_HEAP_SNAPSHOT: 1 << 16
-};
-
-
-/**
* Resets debugger agent to its initial state.
*/
devtools.DebuggerAgent.prototype.reset = function() {
@@ -171,10 +129,6 @@ devtools.DebuggerAgent.prototype.reset = function() {
this.requestNumberToBreakpointInfo_ = {};
this.callFrames_ = [];
this.requestSeqToCallback_ = {};
-
- // Profiler isn't reset because it contains no data that is
- // specific for a particular V8 instance. All such data is
- // managed by an agent on the Render's side.
};
@@ -668,77 +622,6 @@ devtools.DebuggerAgent.prototype.resolveCompletionsOnFrame = function(
/**
- * Sets up callbacks that deal with profiles processing.
- */
-devtools.DebuggerAgent.prototype.setupProfilerProcessorCallbacks = function() {
- // A temporary icon indicating that the profile is being processed.
- var processingIcon = new WebInspector.SidebarTreeElement(
- 'profile-sidebar-tree-item',
- WebInspector.UIString('Processing...'),
- '', null, false);
- var profilesSidebar = WebInspector.panels.profiles.getProfileType(
- WebInspector.CPUProfileType.TypeId).treeElement;
-
- this.profilerProcessor_.setCallbacks(
- function onProfileProcessingStarted() {
- // Set visually empty string. Subtitle hiding is done via styles
- // manipulation which doesn't play well with dynamic append / removal.
- processingIcon.subtitle = ' ';
- profilesSidebar.appendChild(processingIcon);
- },
- function onProfileProcessingStatus(ticksCount) {
- processingIcon.subtitle =
- WebInspector.UIString('%d ticks processed', ticksCount);
- },
- function onProfileProcessingFinished(profile) {
- profilesSidebar.removeChild(processingIcon);
- profile.typeId = WebInspector.CPUProfileType.TypeId;
- InspectorBackend.addFullProfile(profile);
- WebInspector.addProfileHeader(profile);
- // If no profile is currently shown, show the new one.
- var profilesPanel = WebInspector.panels.profiles;
- if (!profilesPanel.visibleView) {
- profilesPanel.showProfile(profile);
- }
- }
- );
-};
-
-
-/**
- * Initializes profiling state.
- */
-devtools.DebuggerAgent.prototype.initializeProfiling = function() {
- this.setupProfilerProcessorCallbacks();
- this.forceGetLogLines_ = true;
- this.getActiveProfilerModulesInterval_ = setInterval(
- function() { RemoteDebuggerAgent.GetActiveProfilerModules(); }, 1000);
-};
-
-
-/**
- * Starts profiling.
- * @param {number} modules List of modules to enable.
- */
-devtools.DebuggerAgent.prototype.startProfiling = function(modules) {
- RemoteDebuggerAgent.StartProfiling(modules);
- if (modules &
- devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_HEAP_SNAPSHOT) {
- // Active modules will not change, instead, a snapshot will be logged.
- RemoteDebuggerAgent.GetNextLogLines();
- }
-};
-
-
-/**
- * Stops profiling.
- */
-devtools.DebuggerAgent.prototype.stopProfiling = function(modules) {
- RemoteDebuggerAgent.StopProfiling(modules);
-};
-
-
-/**
* @param{number} scriptId
* @return {string} Type of the context of the script with specified id.
*/
@@ -1041,43 +924,6 @@ devtools.DebuggerAgent.prototype.handleAfterCompileEvent_ = function(msg) {
/**
- * Handles current profiler status.
- * @param {number} modules List of active (started) modules.
- */
-devtools.DebuggerAgent.prototype.didGetActiveProfilerModules_ = function(
- modules) {
- var profModules = devtools.DebuggerAgent.ProfilerModules;
- var profModuleNone = profModules.PROFILER_MODULE_NONE;
- if (this.forceGetLogLines_ ||
- (modules != profModuleNone &&
- this.activeProfilerModules_ == profModuleNone)) {
- this.forceGetLogLines_ = false;
- // Start to query log data.
- RemoteDebuggerAgent.GetNextLogLines();
- }
- this.activeProfilerModules_ = modules;
- // Update buttons.
- WebInspector.setRecordingProfile(modules & profModules.PROFILER_MODULE_CPU);
-};
-
-
-/**
- * Handles a portion of a profiler log retrieved by GetNextLogLines call.
- * @param {string} log A portion of profiler log.
- */
-devtools.DebuggerAgent.prototype.didGetNextLogLines_ = function(log) {
- if (log.length > 0) {
- this.profilerProcessor_.processLogChunk(log);
- } else if (this.activeProfilerModules_ ==
- devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE) {
- // No new data and profiling is stopped---suspend log reading.
- return;
- }
- setTimeout(function() { RemoteDebuggerAgent.GetNextLogLines(); }, 500);
-};
-
-
-/**
* Adds the script info to the local cache. This method assumes that the script
* is not in the cache yet.
* @param {Object} script Script json object from the debugger message.
diff --git a/webkit/glue/devtools/js/devtools.js b/webkit/glue/devtools/js/devtools.js
index f00b9a4..494b600 100644
--- a/webkit/glue/devtools/js/devtools.js
+++ b/webkit/glue/devtools/js/devtools.js
@@ -42,6 +42,7 @@ devtools.ToolsAgent = function() {
RemoteToolsAgent.DispatchOnClient =
goog.bind(this.dispatchOnClient_, this);
this.debuggerAgent_ = new devtools.DebuggerAgent();
+ this.profilerAgent_ = new devtools.ProfilerAgent();
};
@@ -51,6 +52,7 @@ devtools.ToolsAgent = function() {
devtools.ToolsAgent.prototype.reset = function() {
InspectorFrontendHost.reset();
this.debuggerAgent_.reset();
+ this.profilerAgent_.reset();
};
@@ -75,6 +77,14 @@ devtools.ToolsAgent.prototype.getDebuggerAgent = function() {
/**
+ * @return {devtools.ProfilerAgent} Profiler agent instance.
+ */
+devtools.ToolsAgent.prototype.getProfilerAgent = function() {
+ return this.profilerAgent_;
+};
+
+
+/**
* @param {string} url Url frame navigated to.
* @see tools_agent.h
* @private
@@ -319,7 +329,7 @@ WebInspector.ScriptsPanel.prototype.__defineGetter__(
(function InterceptProfilesPanelEvents() {
var oldShow = WebInspector.ProfilesPanel.prototype.show;
WebInspector.ProfilesPanel.prototype.show = function() {
- devtools.tools.getDebuggerAgent().initializeProfiling();
+ devtools.tools.getProfilerAgent().initializeProfiling();
this.enableToggleButton.visible = false;
oldShow.call(this);
// Show is called on every show event of a panel, so
diff --git a/webkit/glue/devtools/js/devtools_host_stub.js b/webkit/glue/devtools/js/devtools_host_stub.js
index cf3831c..8eb1428 100644
--- a/webkit/glue/devtools/js/devtools_host_stub.js
+++ b/webkit/glue/devtools/js/devtools_host_stub.js
@@ -13,11 +13,6 @@ if (!window['RemoteDebuggerAgent']) {
* @constructor
*/
RemoteDebuggerAgentStub = function() {
- this.activeProfilerModules_ =
- devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE;
- this.profileLogPos_ = 0;
- this.heapProfSample_ = 0;
- this.heapProfLog_ = '';
};
@@ -26,82 +21,112 @@ RemoteDebuggerAgentStub.prototype.GetContextId = function() {
};
-RemoteDebuggerAgentStub.prototype.StopProfiling = function(modules) {
+/**
+ * @constructor
+ */
+RemoteProfilerAgentStub = function() {
+};
+
+
+RemoteProfilerAgentStub.prototype.GetActiveProfilerModules = function() {
+ ProfilerStubHelper.GetInstance().GetActiveProfilerModules();
+};
+
+
+RemoteProfilerAgentStub.prototype.GetLogLines = function(pos) {
+ ProfilerStubHelper.GetInstance().GetLogLines(pos);
+};
+
+
+/**
+ * @constructor
+ */
+RemoteToolsAgentStub = function() {
+};
+
+
+RemoteToolsAgentStub.prototype.DispatchOnInjectedScript = function() {
+};
+
+
+RemoteToolsAgentStub.prototype.DispatchOnInspectorController = function() {
+};
+
+
+RemoteToolsAgentStub.prototype.ExecuteVoidJavaScript = function() {
+};
+
+
+/**
+ * @constructor
+ */
+ProfilerStubHelper = function() {
+ this.activeProfilerModules_ =
+ devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_NONE;
+ this.heapProfSample_ = 0;
+ this.log_ = '';
+};
+
+
+ProfilerStubHelper.GetInstance = function() {
+ if (!ProfilerStubHelper.instance_) {
+ ProfilerStubHelper.instance_ = new ProfilerStubHelper();
+ }
+ return ProfilerStubHelper.instance_;
+};
+
+
+ProfilerStubHelper.prototype.StopProfiling = function(modules) {
this.activeProfilerModules_ &= ~modules;
};
-RemoteDebuggerAgentStub.prototype.StartProfiling = function(modules) {
- var profModules = devtools.DebuggerAgent.ProfilerModules;
+ProfilerStubHelper.prototype.StartProfiling = function(modules) {
+ var profModules = devtools.ProfilerAgent.ProfilerModules;
if (modules & profModules.PROFILER_MODULE_HEAP_SNAPSHOT) {
if (modules & profModules.PROFILER_MODULE_HEAP_STATS) {
- this.heapProfLog_ +=
+ this.log_ +=
'heap-sample-begin,"Heap","allocated",' +
(new Date()).getTime() + '\n' +
'heap-sample-stats,"Heap","allocated",10000,1000\n';
- this.heapProfLog_ +=
+ this.log_ +=
'heap-sample-item,STRING_TYPE,100,1000\n' +
'heap-sample-item,CODE_TYPE,10,200\n' +
'heap-sample-item,MAP_TYPE,20,350\n';
- this.heapProfLog_ += RemoteDebuggerAgentStub.HeapSamples[this.heapProfSample_++];
- this.heapProfSample_ %= RemoteDebuggerAgentStub.HeapSamples.length;
- this.heapProfLog_ +=
+ this.log_ +=
+ ProfilerStubHelper.HeapSamples[this.heapProfSample_++];
+ this.heapProfSample_ %= ProfilerStubHelper.HeapSamples.length;
+ this.log_ +=
'heap-sample-end,"Heap","allocated"\n';
}
} else {
+ if (modules & profModules.PROFILER_MODULE_CPU) {
+ this.log_ += ProfilerStubHelper.ProfilerLogBuffer;
+ }
this.activeProfilerModules_ |= modules;
}
};
-RemoteDebuggerAgentStub.prototype.GetActiveProfilerModules = function() {
+ProfilerStubHelper.prototype.GetActiveProfilerModules = function() {
var self = this;
setTimeout(function() {
- RemoteDebuggerAgent.DidGetActiveProfilerModules(
+ RemoteProfilerAgent.DidGetActiveProfilerModules(
self.activeProfilerModules_);
}, 100);
};
-RemoteDebuggerAgentStub.prototype.GetNextLogLines = function() {
- var profModules = devtools.DebuggerAgent.ProfilerModules;
- var logLines = '';
- if (this.activeProfilerModules_ & profModules.PROFILER_MODULE_CPU) {
- if (this.profileLogPos_ < RemoteDebuggerAgentStub.ProfilerLogBuffer.length) {
- this.profileLogPos_ += RemoteDebuggerAgentStub.ProfilerLogBuffer.length;
- logLines += RemoteDebuggerAgentStub.ProfilerLogBuffer;
- }
- }
- if (this.heapProfLog_) {
- logLines += this.heapProfLog_;
- this.heapProfLog_ = '';
- }
+ProfilerStubHelper.prototype.GetLogLines = function(pos) {
+ var profModules = devtools.ProfilerAgent.ProfilerModules;
+ var logLines = this.log_.substr(pos);
setTimeout(function() {
- RemoteDebuggerAgent.DidGetNextLogLines(logLines);
+ RemoteProfilerAgent.DidGetLogLines(pos + logLines.length, logLines);
}, 100);
};
-/**
- * @constructor
- */
-RemoteToolsAgentStub = function() {
-};
-
-
-RemoteToolsAgentStub.prototype.DispatchOnInjectedScript = function() {
-};
-
-
-RemoteToolsAgentStub.prototype.DispatchOnInspectorController = function() {
-};
-
-
-RemoteToolsAgentStub.prototype.ExecuteVoidJavaScript = function() {
-};
-
-
-RemoteDebuggerAgentStub.ProfilerLogBuffer =
+ProfilerStubHelper.ProfilerLogBuffer =
'profiler,begin,1\n' +
'profiler,resume\n' +
'code-creation,LazyCompile,0x1000,256,"test1 http://aaa.js:1"\n' +
@@ -118,7 +143,7 @@ RemoteDebuggerAgentStub.ProfilerLogBuffer =
'profiler,pause\n';
-RemoteDebuggerAgentStub.HeapSamples = [
+ProfilerStubHelper.HeapSamples = [
'heap-js-cons-item,foo,1,100\n' +
'heap-js-cons-item,bar,20,2000\n' +
'heap-js-cons-item,Object,5,100\n' +
@@ -191,6 +216,17 @@ RemoteDebuggerCommandExecutorStub.prototype.DebuggerCommand = function(cmd) {
'"sourceLength":244,"scriptType":2,"compilationType":0,"context":{' +
'"ref":0}}],"refs":[{"handle":0,"type":"context","data":"page,3}],"' +
'"running":false}');
+ } else if (cmd.indexOf('"command":"profile"') != -1) {
+ var cmdObj = JSON.parse(cmd);
+ if (cmdObj.arguments.command == 'resume') {
+ ProfilerStubHelper.GetInstance().StartProfiling(
+ parseInt(cmdObj.arguments.modules));
+ } else if (cmdObj.arguments.command == 'pause') {
+ ProfilerStubHelper.GetInstance().StopProfiling(
+ parseInt(cmdObj.arguments.modules));
+ } else {
+ debugPrint('Unexpected profile command: ' + cmdObj.arguments.command);
+ }
} else {
debugPrint('Unexpected command: ' + cmd);
}
@@ -230,6 +266,7 @@ DevToolsHostStub.prototype.setSetting = function() {
window['RemoteDebuggerAgent'] = new RemoteDebuggerAgentStub();
window['RemoteDebuggerCommandExecutor'] =
new RemoteDebuggerCommandExecutorStub();
+window['RemoteProfilerAgent'] = new RemoteProfilerAgentStub();
window['RemoteToolsAgent'] = new RemoteToolsAgentStub();
InspectorFrontendHost = new DevToolsHostStub();
diff --git a/webkit/glue/devtools/js/inspector_controller_impl.js b/webkit/glue/devtools/js/inspector_controller_impl.js
index c9b6cd3..02c44c9 100644
--- a/webkit/glue/devtools/js/inspector_controller_impl.js
+++ b/webkit/glue/devtools/js/inspector_controller_impl.js
@@ -135,8 +135,8 @@ devtools.InspectorBackendImpl.prototype.setPauseOnExceptions = function(
* @override
*/
devtools.InspectorBackendImpl.prototype.startProfiling = function() {
- devtools.tools.getDebuggerAgent().startProfiling(
- devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_CPU);
+ devtools.tools.getProfilerAgent().startProfiling(
+ devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_CPU);
};
@@ -144,8 +144,8 @@ devtools.InspectorBackendImpl.prototype.startProfiling = function() {
* @override
*/
devtools.InspectorBackendImpl.prototype.stopProfiling = function() {
- devtools.tools.getDebuggerAgent().stopProfiling(
- devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_CPU);
+ devtools.tools.getProfilerAgent().stopProfiling(
+ devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_CPU);
};
@@ -181,10 +181,10 @@ devtools.InspectorBackendImpl.prototype.getProfile = function(callId, uid) {
* @override
*/
devtools.InspectorBackendImpl.prototype.takeHeapSnapshot = function() {
- devtools.tools.getDebuggerAgent().startProfiling(
- devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_HEAP_SNAPSHOT
- | devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_HEAP_STATS
- | devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_JS_CONSTRUCTORS);
+ devtools.tools.getProfilerAgent().startProfiling(
+ devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_HEAP_SNAPSHOT
+ | devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_HEAP_STATS
+ | devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_JS_CONSTRUCTORS);
};
diff --git a/webkit/glue/devtools/js/profiler_agent.js b/webkit/glue/devtools/js/profiler_agent.js
new file mode 100644
index 0000000..c41bbcb
--- /dev/null
+++ b/webkit/glue/devtools/js/profiler_agent.js
@@ -0,0 +1,191 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Provides communication interface to remote v8 profiler.
+ */
+goog.provide('devtools.ProfilerAgent');
+
+/**
+ * @constructor
+ */
+devtools.ProfilerAgent = function() {
+ RemoteProfilerAgent.DidGetActiveProfilerModules =
+ goog.bind(this.didGetActiveProfilerModules_, this);
+ RemoteProfilerAgent.DidGetLogLines =
+ goog.bind(this.didGetLogLines_, this);
+
+ /**
+ * Active profiler modules flags.
+ * @type {number}
+ */
+ this.activeProfilerModules_ =
+ devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_NONE;
+
+ /**
+ * Interval for polling profiler state.
+ * @type {number}
+ */
+ this.getActiveProfilerModulesInterval_ = null;
+
+ /**
+ * Profiler log position.
+ * @type {number}
+ */
+ this.logPosition_ = 0;
+
+ /**
+ * Whether log contents retrieval must be forced next time.
+ * @type {boolean}
+ */
+ this.forceGetLogLines_ = false;
+
+ /**
+ * Profiler processor instance.
+ * @type {devtools.profiler.Processor}
+ */
+ this.profilerProcessor_ = new devtools.profiler.Processor();
+};
+
+
+/**
+ * A copy of enum from include/v8.h
+ * @enum {number}
+ */
+devtools.ProfilerAgent.ProfilerModules = {
+ PROFILER_MODULE_NONE: 0,
+ PROFILER_MODULE_CPU: 1,
+ PROFILER_MODULE_HEAP_STATS: 1 << 1,
+ PROFILER_MODULE_JS_CONSTRUCTORS: 1 << 2,
+ PROFILER_MODULE_HEAP_SNAPSHOT: 1 << 16
+};
+
+
+/**
+ * Resets profiler agent to its initial state.
+ */
+devtools.ProfilerAgent.prototype.reset = function() {
+ this.logPosition_ = 0;
+ this.activeProfilerModules_ =
+ devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_NONE;
+};
+
+
+/**
+ * Sets up callbacks that deal with profiles processing.
+ */
+devtools.ProfilerAgent.prototype.setupProfilerProcessorCallbacks = function() {
+ // A temporary icon indicating that the profile is being processed.
+ var processingIcon = new WebInspector.SidebarTreeElement(
+ 'profile-sidebar-tree-item',
+ WebInspector.UIString('Processing...'),
+ '', null, false);
+ var profilesSidebar = WebInspector.panels.profiles.getProfileType(
+ WebInspector.CPUProfileType.TypeId).treeElement;
+
+ this.profilerProcessor_.setCallbacks(
+ function onProfileProcessingStarted() {
+ // Set visually empty string. Subtitle hiding is done via styles
+ // manipulation which doesn't play well with dynamic append / removal.
+ processingIcon.subtitle = ' ';
+ profilesSidebar.appendChild(processingIcon);
+ },
+ function onProfileProcessingStatus(ticksCount) {
+ processingIcon.subtitle =
+ WebInspector.UIString('%d ticks processed', ticksCount);
+ },
+ function onProfileProcessingFinished(profile) {
+ profilesSidebar.removeChild(processingIcon);
+ profile.typeId = WebInspector.CPUProfileType.TypeId;
+ InspectorBackend.addFullProfile(profile);
+ WebInspector.addProfileHeader(profile);
+ // If no profile is currently shown, show the new one.
+ var profilesPanel = WebInspector.panels.profiles;
+ if (!profilesPanel.visibleView) {
+ profilesPanel.showProfile(profile);
+ }
+ }
+ );
+};
+
+
+/**
+ * Initializes profiling state.
+ */
+devtools.ProfilerAgent.prototype.initializeProfiling = function() {
+ this.setupProfilerProcessorCallbacks();
+ this.forceGetLogLines_ = true;
+ this.getActiveProfilerModulesInterval_ = setInterval(
+ function() { RemoteProfilerAgent.GetActiveProfilerModules(); }, 1000);
+};
+
+
+/**
+ * Starts profiling.
+ * @param {number} modules List of modules to enable.
+ */
+devtools.ProfilerAgent.prototype.startProfiling = function(modules) {
+ var cmd = new devtools.DebugCommand('profile', {
+ 'modules': modules,
+ 'command': 'resume'});
+ devtools.DebuggerAgent.sendCommand_(cmd);
+ RemoteToolsAgent.ExecuteVoidJavaScript();
+ if (modules &
+ devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_HEAP_SNAPSHOT) {
+ var pos = this.logPosition_;
+ // Active modules will not change, instead, a snapshot will be logged.
+ setTimeout(function() { RemoteProfilerAgent.GetLogLines(pos); }, 500);
+ }
+};
+
+
+/**
+ * Stops profiling.
+ */
+devtools.ProfilerAgent.prototype.stopProfiling = function(modules) {
+ var cmd = new devtools.DebugCommand('profile', {
+ 'modules': modules,
+ 'command': 'pause'});
+ devtools.DebuggerAgent.sendCommand_(cmd);
+ RemoteToolsAgent.ExecuteVoidJavaScript();
+};
+
+
+/**
+ * Handles current profiler status.
+ * @param {number} modules List of active (started) modules.
+ */
+devtools.ProfilerAgent.prototype.didGetActiveProfilerModules_ = function(
+ modules) {
+ var profModules = devtools.ProfilerAgent.ProfilerModules;
+ var profModuleNone = profModules.PROFILER_MODULE_NONE;
+ if (this.forceGetLogLines_ ||
+ (modules != profModuleNone &&
+ this.activeProfilerModules_ == profModuleNone)) {
+ this.forceGetLogLines_ = false;
+ // Start to query log data.
+ RemoteProfilerAgent.GetLogLines(this.logPosition_);
+ }
+ this.activeProfilerModules_ = modules;
+ // Update buttons.
+ WebInspector.setRecordingProfile(modules & profModules.PROFILER_MODULE_CPU);
+};
+
+
+/**
+ * Handles a portion of a profiler log retrieved by GetLogLines call.
+ * @param {number} pos Current position in log.
+ * @param {string} log A portion of profiler log.
+ */
+devtools.ProfilerAgent.prototype.didGetLogLines_ = function(pos, log) {
+ this.logPosition_ = pos;
+ if (log.length > 0) {
+ this.profilerProcessor_.processLogChunk(log);
+ } else if (this.activeProfilerModules_ ==
+ devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_NONE) {
+ // No new data and profiling is stopped---suspend log reading.
+ return;
+ }
+ setTimeout(function() { RemoteProfilerAgent.GetLogLines(pos); }, 500);
+};
diff --git a/webkit/glue/devtools/js/tests.js b/webkit/glue/devtools/js/tests.js
index 1136f50..0eb2a42 100644
--- a/webkit/glue/devtools/js/tests.js
+++ b/webkit/glue/devtools/js/tests.js
@@ -430,8 +430,8 @@ TestSuite.prototype.testProfilerTab = function() {
});
var ticksCount = 0;
var tickRecord = '\nt,';
- this.addSniffer(RemoteDebuggerAgent, 'DidGetNextLogLines',
- function(log) {
+ this.addSniffer(RemoteProfilerAgent, 'DidGetLogLines',
+ function(posIgnored, log) {
var pos = 0;
while ((pos = log.indexOf(tickRecord, pos)) != -1) {
pos += tickRecord.length;
diff --git a/webkit/glue/devtools/profiler_agent.h b/webkit/glue/devtools/profiler_agent.h
new file mode 100644
index 0000000..c285401
--- /dev/null
+++ b/webkit/glue/devtools/profiler_agent.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_DEVTOOLS_PROFILER_AGENT_H_
+#define WEBKIT_GLUE_DEVTOOLS_PROFILER_AGENT_H_
+
+#include "webkit/glue/devtools/devtools_rpc.h"
+
+// Profiler agent provides API for retrieving profiler data.
+// These methods are handled on the IO thread, so profiler can
+// operate while a script on a page performs heavy work.
+#define PROFILER_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \
+ /* Requests current profiler state. */ \
+ METHOD0(GetActiveProfilerModules) \
+ \
+ /* Retrieves portion of profiler log. */ \
+ METHOD1(GetLogLines, int /* position */)
+
+DEFINE_RPC_CLASS(ProfilerAgent, PROFILER_AGENT_STRUCT)
+
+#define PROFILER_AGENT_DELEGATE_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3) \
+ /* Response to GetActiveProfilerModules. */ \
+ METHOD1(DidGetActiveProfilerModules, int /* flags */) \
+ \
+ /* Response to GetLogLines. */ \
+ METHOD2(DidGetLogLines, int /* position */, String /* log */)
+
+DEFINE_RPC_CLASS(ProfilerAgentDelegate, PROFILER_AGENT_DELEGATE_STRUCT)
+
+#endif // WEBKIT_GLUE_DEVTOOLS_PROFILER_AGENT_H_
diff --git a/webkit/glue/devtools/profiler_agent_impl.cc b/webkit/glue/devtools/profiler_agent_impl.cc
new file mode 100644
index 0000000..27779d4
--- /dev/null
+++ b/webkit/glue/devtools/profiler_agent_impl.cc
@@ -0,0 +1,23 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+
+#undef LOG
+
+#include "webkit/glue/devtools/profiler_agent_impl.h"
+
+void ProfilerAgentImpl::GetActiveProfilerModules() {
+ delegate_->DidGetActiveProfilerModules(
+ v8::V8::GetActiveProfilerModules());
+}
+
+void ProfilerAgentImpl::GetLogLines(int position) {
+ static char buffer[65536];
+ const int read_size = v8::V8::GetLogLines(
+ position, buffer, sizeof(buffer) - 1);
+ buffer[read_size] = '\0';
+ position += read_size;
+ delegate_->DidGetLogLines(position, buffer);
+}
diff --git a/webkit/glue/devtools/profiler_agent_impl.h b/webkit/glue/devtools/profiler_agent_impl.h
new file mode 100644
index 0000000..e604809
--- /dev/null
+++ b/webkit/glue/devtools/profiler_agent_impl.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_DEVTOOLS_PROFILER_AGENT_IMPL_H_
+#define WEBKIT_GLUE_DEVTOOLS_PROFILER_AGENT_IMPL_H_
+
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+
+#include "base/basictypes.h"
+#include "v8.h"
+#include "webkit/glue/devtools/profiler_agent.h"
+
+class ProfilerAgentImpl : public ProfilerAgent {
+ public:
+ ProfilerAgentImpl(ProfilerAgentDelegate* delegate)
+ : delegate_(delegate) {}
+ virtual ~ProfilerAgentImpl() {}
+
+ // ProfilerAgent implementation.
+
+ // This method is called on IO thread.
+ virtual void GetActiveProfilerModules();
+
+ // This method is called on IO thread.
+ virtual void GetLogLines(int position);
+
+ private:
+ ProfilerAgentDelegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProfilerAgentImpl);
+};
+
+#endif // WEBKIT_GLUE_DEVTOOLS_PROFILER_AGENT_IMPL_H_
diff --git a/webkit/glue/webdevtoolsagent_impl.cc b/webkit/glue/webdevtoolsagent_impl.cc
index 43ebc89..ab8d955 100644
--- a/webkit/glue/webdevtoolsagent_impl.cc
+++ b/webkit/glue/webdevtoolsagent_impl.cc
@@ -41,6 +41,7 @@
#include "webkit/glue/devtools/bound_object.h"
#include "webkit/glue/devtools/debugger_agent_impl.h"
#include "webkit/glue/devtools/debugger_agent_manager.h"
+#include "webkit/glue/devtools/profiler_agent_impl.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/webdevtoolsagent_impl.h"
@@ -112,6 +113,27 @@ static const char kApuAgentFeatureName[] = "apu-agent";
static const char kTimelineFeatureName[] = "timeline-profiler";
static const char kResourceTrackingFeatureName[] = "resource-tracking";
+class IoRpcDelegate : public DevToolsRpc::Delegate {
+ public:
+ IoRpcDelegate() {}
+ virtual ~IoRpcDelegate() {}
+ virtual void SendRpcMessage(const String& class_name,
+ const String& method_name,
+ const String& p1,
+ const String& p2,
+ const String& p3) {
+ WebDevToolsAgentClient::sendMessageToFrontendOnIOThread(
+ webkit_glue::StringToWebString(class_name),
+ webkit_glue::StringToWebString(method_name),
+ webkit_glue::StringToWebString(p1),
+ webkit_glue::StringToWebString(p2),
+ webkit_glue::StringToWebString(p3));
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IoRpcDelegate);
+};
+
} // namespace
WebDevToolsAgentImpl::WebDevToolsAgentImpl(
@@ -604,4 +626,23 @@ void WebDevToolsAgent::setMessageLoopDispatchHandler(
DebuggerAgentManager::SetMessageLoopDispatchHandler(handler);
}
+// static
+bool WebDevToolsAgent::dispatchMessageFromFrontendOnIOThread(
+ const WebString& className,
+ const WebString& methodName,
+ const WebString& param1,
+ const WebString& param2,
+ const WebString& param3) {
+ IoRpcDelegate transport;
+ ProfilerAgentDelegateStub stub(&transport);
+ ProfilerAgentImpl agent(&stub);
+ return ProfilerAgentDispatch::Dispatch(
+ &agent,
+ webkit_glue::WebStringToString(className),
+ webkit_glue::WebStringToString(methodName),
+ webkit_glue::WebStringToString(param1),
+ webkit_glue::WebStringToString(param2),
+ webkit_glue::WebStringToString(param3));
+}
+
} // namespace WebKit
diff --git a/webkit/glue/webdevtoolsfrontend_impl.cc b/webkit/glue/webdevtoolsfrontend_impl.cc
index 400c284..eaa3038 100644
--- a/webkit/glue/webdevtoolsfrontend_impl.cc
+++ b/webkit/glue/webdevtoolsfrontend_impl.cc
@@ -33,6 +33,7 @@
#include "webkit/glue/devtools/bound_object.h"
#include "webkit/glue/devtools/debugger_agent.h"
#include "webkit/glue/devtools/devtools_rpc_js.h"
+#include "webkit/glue/devtools/profiler_agent.h"
#include "webkit/glue/devtools/tools_agent.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/webdevtoolsfrontend_impl.h"
@@ -57,6 +58,8 @@ static v8::Local<v8::String> ToV8String(const String& s) {
DEFINE_RPC_JS_BOUND_OBJ(DebuggerAgent, DEBUGGER_AGENT_STRUCT,
DebuggerAgentDelegate, DEBUGGER_AGENT_DELEGATE_STRUCT)
+DEFINE_RPC_JS_BOUND_OBJ(ProfilerAgent, PROFILER_AGENT_STRUCT,
+ ProfilerAgentDelegate, PROFILER_AGENT_DELEGATE_STRUCT)
DEFINE_RPC_JS_BOUND_OBJ(ToolsAgent, TOOLS_AGENT_STRUCT,
ToolsAgentDelegate, TOOLS_AGENT_DELEGATE_STRUCT)
@@ -134,6 +137,8 @@ WebDevToolsFrontendImpl::WebDevToolsFrontendImpl(
debugger_agent_obj_.set(new JsDebuggerAgentBoundObj(
this, frame_context, "RemoteDebuggerAgent"));
+ profiler_agent_obj_.set(new JsProfilerAgentBoundObj(
+ this, frame_context, "RemoteProfilerAgent"));
tools_agent_obj_.set(
new JsToolsAgentBoundObj(this, frame_context, "RemoteToolsAgent"));
diff --git a/webkit/glue/webdevtoolsfrontend_impl.h b/webkit/glue/webdevtoolsfrontend_impl.h
index 7540c7d..769a612 100644
--- a/webkit/glue/webdevtoolsfrontend_impl.h
+++ b/webkit/glue/webdevtoolsfrontend_impl.h
@@ -29,6 +29,7 @@ class WebViewImpl;
class BoundObject;
class JsDebuggerAgentBoundObj;
class JsNetAgentBoundObj;
+class JsProfilerAgentBoundObj;
class JsToolsAgentBoundObj;
class ToolsAgentNativeDelegateImpl;
class WebDevToolsClientDelegate;
@@ -95,6 +96,7 @@ class WebDevToolsFrontendImpl : public WebKit::WebDevToolsFrontend,
String application_locale_;
OwnPtr<BoundObject> debugger_command_executor_obj_;
OwnPtr<JsDebuggerAgentBoundObj> debugger_agent_obj_;
+ OwnPtr<JsProfilerAgentBoundObj> profiler_agent_obj_;
OwnPtr<JsToolsAgentBoundObj> tools_agent_obj_;
bool loaded_;
Vector<Vector<String> > pending_incoming_messages_;
diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp
index eaf5fff..cabf4cb 100644
--- a/webkit/webkit.gyp
+++ b/webkit/webkit.gyp
@@ -33,6 +33,7 @@
'../v8/tools/profile.js',
'../v8/tools/profile_view.js',
'../v8/tools/splaytree.js',
+ 'glue/devtools/js/profiler_agent.js',
'glue/devtools/js/profiler_processor.js',
'glue/devtools/js/heap_profiler_panel.js',
'glue/devtools/js/devtools.js',
@@ -245,6 +246,9 @@
'glue/devtools/debugger_agent_impl.h',
'glue/devtools/debugger_agent_manager.cc',
'glue/devtools/debugger_agent_manager.h',
+ 'glue/devtools/profiler_agent.h',
+ 'glue/devtools/profiler_agent_impl.cc',
+ 'glue/devtools/profiler_agent_impl.h',
'glue/devtools/tools_agent.h',
'glue/media/buffered_data_source.cc',
'glue/media/buffered_data_source.h',