diff options
author | mnaganov@chromium.org <mnaganov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-04 09:45:05 +0000 |
---|---|---|
committer | mnaganov@chromium.org <mnaganov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-04 09:45:05 +0000 |
commit | ac6b48ef70b3746562ef21ddf34c18ffe7efc256 (patch) | |
tree | 822ca5abf284701619cc9e7358cdb2866ac735fb /webkit | |
parent | bb58bb3557416bf429d7960f3129aee39a3936fc (diff) | |
download | chromium_src-ac6b48ef70b3746562ef21ddf34c18ffe7efc256.zip chromium_src-ac6b48ef70b3746562ef21ddf34c18ffe7efc256.tar.gz chromium_src-ac6b48ef70b3746562ef21ddf34c18ffe7efc256.tar.bz2 |
DevTools Profiler: reuse more code from WebKit Inspector.
This enables:
- links to source code from call graph tree;
- focusing and exlusion of functions;
- search (but it seems not fully-functional in WebKit Inspector for now).
Also moved to profiler_processor WebKit-specific code from V8/tools/profile_view.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/118230
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17626 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/glue/devtools/js/devtools.html | 2 | ||||
-rw-r--r-- | webkit/glue/devtools/js/devtools.js | 95 | ||||
-rw-r--r-- | webkit/glue/devtools/js/devtools_host_stub.js | 1 | ||||
-rw-r--r-- | webkit/glue/devtools/js/profiler_processor.js | 131 | ||||
-rw-r--r-- | webkit/webkit.gyp | 2 |
5 files changed, 120 insertions, 111 deletions
diff --git a/webkit/glue/devtools/js/devtools.html b/webkit/glue/devtools/js/devtools.html index 922b584..b10e208 100644 --- a/webkit/glue/devtools/js/devtools.html +++ b/webkit/glue/devtools/js/devtools.html @@ -101,6 +101,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="ScriptView.js"></script> <script type="text/javascript" src="ProfileView.js"></script> <script type="text/javascript" src="ProfileDataGridTree.js"></script> + <script type="text/javascript" src="BottomUpProfileDataGridTree.js"></script> + <script type="text/javascript" src="TopDownProfileDataGridTree.js"></script> <script type="text/javascript" src="devtools.js"></script> <script type="text/javascript" src="devtools_host_stub.js"></script> </head> diff --git a/webkit/glue/devtools/js/devtools.js b/webkit/glue/devtools/js/devtools.js index a21eeda..5ed05c2 100644 --- a/webkit/glue/devtools/js/devtools.js +++ b/webkit/glue/devtools/js/devtools.js @@ -851,101 +851,6 @@ WebInspector.Console.prototype._evalInInspectedWindow = function(expression) { })(); -/** - * We don't use WebKit's BottomUpProfileDataGridTree, instead using - * our own (because BottomUpProfileDataGridTree's functionality is - * implemented in profile_view.js for V8's Tick Processor). - * - * @param {WebInspector.ProfileView} profileView Profile view. - * @param {devtools.profiler.ProfileView} profile Profile. - */ -WebInspector.BottomUpProfileDataGridTree = function(profileView, profile) { - return WebInspector.buildProfileDataGridTree_( - profileView, profile.heavyProfile); -}; - - -/** - * We don't use WebKit's TopDownProfileDataGridTree, instead using - * our own (because TopDownProfileDataGridTree's functionality is - * implemented in profile_view.js for V8's Tick Processor). - * - * @param {WebInspector.ProfileView} profileView Profile view. - * @param {devtools.profiler.ProfileView} profile Profile. - */ -WebInspector.TopDownProfileDataGridTree = function(profileView, profile) { - return WebInspector.buildProfileDataGridTree_( - profileView, profile.treeProfile); -}; - - -/** - * A helper function, checks whether a profile node has visible children. - * - * @param {devtools.profiler.ProfileView.Node} profileNode Profile node. - * @return {boolean} Whether a profile node has visible children. - */ -WebInspector.nodeHasChildren_ = function(profileNode) { - var children = profileNode.children; - for (var i = 0, n = children.length; i < n; ++i) { - if (children[i].visible) { - return true; - } - } - return false; -}; - - -/** - * Common code for populating a profiler grid node or a tree with - * given profile nodes. - * - * @param {WebInspector.ProfileDataGridNode| - * WebInspector.ProfileDataGridTree} viewNode Grid node or a tree. - * @param {WebInspector.ProfileView} profileView Profile view. - * @param {Array<devtools.profiler.ProfileView.Node>} children Profile nodes. - * @param {WebInspector.ProfileDataGridTree} owningTree Grid tree. - */ -WebInspector.populateNode_ = function( - viewNode, profileView, children, owningTree) { - for (var i = 0, n = children.length; i < n; ++i) { - var child = children[i]; - if (child.visible) { - viewNode.appendChild( - new WebInspector.ProfileDataGridNode( - profileView, child, owningTree, - WebInspector.nodeHasChildren_(child))); - } - } -}; - - -/** - * A helper function for building a profile grid tree. - * - * @param {WebInspector.ProfileView} profileview Profile view. - * @param {devtools.profiler.ProfileView} profile Profile. - * @return {WebInspector.ProfileDataGridTree} Profile grid tree. - */ -WebInspector.buildProfileDataGridTree_ = function(profileView, profile) { - var children = profile.head.children; - var dataGridTree = new WebInspector.ProfileDataGridTree( - profileView, profile.head); - WebInspector.populateNode_(dataGridTree, profileView, children, dataGridTree); - return dataGridTree; -}; - - -/** - * @override - */ -WebInspector.ProfileDataGridNode.prototype._populate = function(event) { - var children = this.profileNode.children; - WebInspector.populateNode_(this, this.profileView, children, this.tree); - this.removeEventListener("populate", this._populate, this); -}; - - // As columns in data grid can't be changed after initialization, // we need to intercept the constructor and modify columns upon creation. (function InterceptDataGridForProfiler() { diff --git a/webkit/glue/devtools/js/devtools_host_stub.js b/webkit/glue/devtools/js/devtools_host_stub.js index fa9aba1..4538e83 100644 --- a/webkit/glue/devtools/js/devtools_host_stub.js +++ b/webkit/glue/devtools/js/devtools_host_stub.js @@ -244,6 +244,7 @@ RemoteToolsAgentStub.prototype.SetResourceTrackingEnabled = function(enabled, al RemoteDebuggerAgentStub.ProfilerLogBuffer = + 'profiler,begin,1\n' + 'profiler,resume\n' + 'code-creation,LazyCompile,0x1000,256,"test1 http://aaa.js:1"\n' + 'code-creation,LazyCompile,0x2000,256,"test2 http://bbb.js:2"\n' + diff --git a/webkit/glue/devtools/js/profiler_processor.js b/webkit/glue/devtools/js/profiler_processor.js index 117afc8..9f06acb3 100644 --- a/webkit/glue/devtools/js/profiler_processor.js +++ b/webkit/glue/devtools/js/profiler_processor.js @@ -11,6 +11,91 @@ goog.provide('devtools.profiler.Processor'); /** + * Creates a Profile View builder object compatible with WebKit Profiler UI. + * + * @param {number} samplingRate Number of ms between profiler ticks. + * @constructor + */ +devtools.profiler.WebKitViewBuilder = function(samplingRate) { + devtools.profiler.ViewBuilder.call(this, samplingRate); +}; +goog.inherits(devtools.profiler.WebKitViewBuilder, + devtools.profiler.ViewBuilder); + + +/** + * @override + */ +devtools.profiler.WebKitViewBuilder.prototype.createViewNode = function( + funcName, totalTime, selfTime, head) { + return new devtools.profiler.WebKitViewNode( + funcName, totalTime, selfTime, head); +}; + + +/** + * Constructs a Profile View node object for displaying in WebKit Profiler UI. + * + * @param {string} internalFuncName A fully qualified function name. + * @param {number} totalTime Amount of time that application spent in the + * corresponding function and its descendants (not that depending on + * profile they can be either callees or callers.) + * @param {number} selfTime Amount of time that application spent in the + * corresponding function only. + * @param {devtools.profiler.ProfileView.Node} head Profile view head. + * @constructor + */ +devtools.profiler.WebKitViewNode = function( + internalFuncName, totalTime, selfTime, head) { + devtools.profiler.ProfileView.Node.call(this, + internalFuncName, totalTime, selfTime, head); + this.initFuncInfo_(); + this.callUID = internalFuncName; +}; +goog.inherits(devtools.profiler.WebKitViewNode, + devtools.profiler.ProfileView.Node); + + +/** + * RegEx for stripping V8's prefixes of compiled functions. + */ +devtools.profiler.WebKitViewNode.FUNC_NAME_STRIP_RE = + /^(?:LazyCompile|Function): (.*)$/; + + +/** + * RegEx for extracting script source URL and line number. + */ +devtools.profiler.WebKitViewNode.FUNC_NAME_PARSE_RE = /^([^ ]+) (.*):(\d+)$/; + + +/** + * Inits 'functionName', 'url', and 'lineNumber' fields using 'internalFuncName' + * field. + * @private + */ +devtools.profiler.WebKitViewNode.prototype.initFuncInfo_ = function() { + var nodeAlias = devtools.profiler.WebKitViewNode; + this.functionName = this.internalFuncName; + + var strippedName = nodeAlias.FUNC_NAME_STRIP_RE.exec(this.functionName); + if (strippedName) { + this.functionName = strippedName[1]; + } + + var parsedName = nodeAlias.FUNC_NAME_PARSE_RE.exec(this.functionName); + if (parsedName) { + this.functionName = parsedName[1]; + this.url = parsedName[2]; + this.lineNumber = parsedName[3]; + } else { + this.url = ''; + this.lineNumber = 0; + } +}; + + +/** * Ancestor of a profile object that leaves out only JS-related functions. * @constructor */ @@ -78,7 +163,7 @@ devtools.profiler.Processor = function(newProfileCallback) { /** * Builder of profile views. Created during "profiler,begin" event processing. - * @type {devtools.profiler.ViewBuilder} + * @type {devtools.profiler.WebKitViewBuilder} */ this.viewBuilder_ = null; @@ -91,6 +176,19 @@ devtools.profiler.Processor = function(newProfileCallback) { /** + * An address for the fake "(program)" entry. WebKit's visualisation + * has assumptions on how the top of the call tree should look like, + * and we need to add a fake entry as the topmost function. This + * address is chosen because it's the end address of the first memory + * page, which is never used for code or data, but only as a guard + * page for catching AV errors. + * + * @type {number} + */ +devtools.profiler.Processor.PROGRAM_ENTRY = 0xffff; + + +/** * A dispatch table for V8 profiler event log records. * @private */ @@ -206,21 +304,26 @@ devtools.profiler.Processor.prototype.dispatchLogRow_ = function(fields) { }; -devtools.profiler.Processor.prototype.processProfiler_ = function(state, params) { +devtools.profiler.Processor.prototype.processProfiler_ = function( + state, params) { switch (state) { - case "resume": + case 'resume': if (this.currentProfile_ == null) { this.currentProfile_ = new devtools.profiler.JsProfile(); this.profiles_.push(this.currentProfile_); + // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY + this.currentProfile_.addCode( + 'Function', '(program)', + devtools.profiler.Processor.PROGRAM_ENTRY, 1); } break; - case "pause": + case 'pause': if (this.currentProfile_ != null) { this.newProfileCallback_(this.createProfileForView()); this.currentProfile_ = null; } break; - case "begin": + case 'begin': var samplingRate = NaN; if (params.length > 0) { samplingRate = parseInt(params[0]); @@ -228,12 +331,12 @@ devtools.profiler.Processor.prototype.processProfiler_ = function(state, params) if (isNaN(samplingRate)) { samplingRate = 1; } - this.viewBuilder_ = new devtools.profiler.ViewBuilder(samplingRate); + this.viewBuilder_ = new devtools.profiler.WebKitViewBuilder(samplingRate); break; // This event is valid but isn't used. - case "end": break; + case 'end': break; default: - throw new Error("unknown profiler state: " + state); + throw new Error('unknown profiler state: ' + state); } }; @@ -264,6 +367,8 @@ devtools.profiler.Processor.prototype.processTick_ = function( fullStack.push(parseInt(frame, 16)); } } + // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY + fullStack.push(devtools.profiler.Processor.PROGRAM_ENTRY); this.currentProfile_.recordTick(fullStack); }; @@ -272,15 +377,9 @@ devtools.profiler.Processor.prototype.processTick_ = function( * Creates a profile for further displaying in ProfileView. */ devtools.profiler.Processor.prototype.createProfileForView = function() { - var profile = new devtools.profiler.ProfileView(); + var profile = this.viewBuilder_.buildView( + this.currentProfile_.getTopDownProfile()); profile.uid = this.profileId_++; profile.title = UserInitiatedProfileName + '.' + profile.uid; - // A trick to cope with ProfileView.bottomUpProfileDataGridTree and - // ProfileView.topDownProfileDataGridTree behavior. - profile.head = profile; - profile.heavyProfile = this.viewBuilder_.buildView( - this.currentProfile_.getBottomUpProfile(), true); - profile.treeProfile = this.viewBuilder_.buildView( - this.currentProfile_.getTopDownProfile()); return profile; }; diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp index 41acb49..6a977bb 100644 --- a/webkit/webkit.gyp +++ b/webkit/webkit.gyp @@ -4640,6 +4640,7 @@ 'inspector/DebuggerIPC.js', 'inspector/DebuggerPanel.js', 'inspector/DebuggerShell.js', + '../third_party/WebKit/WebCore/inspector/front-end/BottomUpProfileDataGridTree.js', '../third_party/WebKit/WebCore/inspector/front-end/Breakpoint.js', '../third_party/WebKit/WebCore/inspector/front-end/BreakpointsSidebarPane.js', '../third_party/WebKit/WebCore/inspector/front-end/CallStackSidebarPane.js', @@ -4681,6 +4682,7 @@ '../third_party/WebKit/WebCore/inspector/front-end/SourceView.js', '../third_party/WebKit/WebCore/inspector/front-end/StylesSidebarPane.js', '../third_party/WebKit/WebCore/inspector/front-end/TextPrompt.js', + '../third_party/WebKit/WebCore/inspector/front-end/TopDownProfileDataGridTree.js', '../third_party/WebKit/WebCore/inspector/front-end/treeoutline.js', '../third_party/WebKit/WebCore/inspector/front-end/utilities.js', '../third_party/WebKit/WebCore/inspector/front-end/View.js', |