diff options
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/glue/devtools/debugger_agent.h | 22 | ||||
-rw-r--r-- | webkit/glue/devtools/debugger_agent_impl.cc | 26 | ||||
-rw-r--r-- | webkit/glue/devtools/debugger_agent_impl.h | 9 | ||||
-rw-r--r-- | webkit/glue/devtools/js/debugger_agent.js | 154 | ||||
-rw-r--r-- | webkit/glue/devtools/js/devtools.js | 12 | ||||
-rw-r--r-- | webkit/glue/devtools/js/devtools_host_stub.js | 137 | ||||
-rw-r--r-- | webkit/glue/devtools/js/inspector_controller_impl.js | 16 | ||||
-rw-r--r-- | webkit/glue/devtools/js/profiler_agent.js | 191 | ||||
-rw-r--r-- | webkit/glue/devtools/js/tests.js | 4 | ||||
-rw-r--r-- | webkit/glue/devtools/profiler_agent.h | 31 | ||||
-rw-r--r-- | webkit/glue/devtools/profiler_agent_impl.cc | 23 | ||||
-rw-r--r-- | webkit/glue/devtools/profiler_agent_impl.h | 35 | ||||
-rw-r--r-- | webkit/glue/webdevtoolsagent_impl.cc | 41 | ||||
-rw-r--r-- | webkit/glue/webdevtoolsfrontend_impl.cc | 5 | ||||
-rw-r--r-- | webkit/glue/webdevtoolsfrontend_impl.h | 2 | ||||
-rw-r--r-- | webkit/webkit.gyp | 4 |
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', |