summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authormnaganov@chromium.org <mnaganov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-04 09:45:05 +0000
committermnaganov@chromium.org <mnaganov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-04 09:45:05 +0000
commitac6b48ef70b3746562ef21ddf34c18ffe7efc256 (patch)
tree822ca5abf284701619cc9e7358cdb2866ac735fb /webkit
parentbb58bb3557416bf429d7960f3129aee39a3936fc (diff)
downloadchromium_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.html2
-rw-r--r--webkit/glue/devtools/js/devtools.js95
-rw-r--r--webkit/glue/devtools/js/devtools_host_stub.js1
-rw-r--r--webkit/glue/devtools/js/profiler_processor.js131
-rw-r--r--webkit/webkit.gyp2
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',