diff options
Diffstat (limited to 'WebKit/chromium/src/js/ProfilerProcessor.js')
-rw-r--r-- | WebKit/chromium/src/js/ProfilerProcessor.js | 543 |
1 files changed, 0 insertions, 543 deletions
diff --git a/WebKit/chromium/src/js/ProfilerProcessor.js b/WebKit/chromium/src/js/ProfilerProcessor.js deleted file mode 100644 index f678d2c..0000000 --- a/WebKit/chromium/src/js/ProfilerProcessor.js +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @fileoverview Profiler processor is used to process log file produced - * by V8 and produce an internal profile representation which is used - * for building profile views in "Profiles" tab. - */ - - -/** - * 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); -}; -devtools.profiler.WebKitViewBuilder.prototype.__proto__ = devtools.profiler.ViewBuilder.prototype; - - -/** - * @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; -}; -devtools.profiler.WebKitViewNode.prototype.__proto__ = devtools.profiler.ProfileView.Node.prototype; - - -/** - * RegEx for stripping V8's prefixes of compiled functions. - */ -devtools.profiler.WebKitViewNode.FUNC_NAME_STRIP_RE = /^(?:LazyCompile|Function|Callback): (.*)$/; - - -/** - * RegEx for extracting script source URL and line number. - */ -devtools.profiler.WebKitViewNode.FUNC_NAME_PARSE_RE = /^((?:get | set )?[^ ]+) (.*):(\d+)( \{\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]; - if (parsedName[4]) - this.functionName += parsedName[4]; - 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 - */ -devtools.profiler.JsProfile = function() -{ - devtools.profiler.Profile.call(this); -}; -devtools.profiler.JsProfile.prototype.__proto__ = devtools.profiler.Profile.prototype; - - -/** - * RegExp that leaves only non-native JS functions. - * @type {RegExp} - */ -devtools.profiler.JsProfile.JS_NON_NATIVE_RE = new RegExp( - "^" + - "(?:Callback:)|" + - "(?:Script: (?!native))|" + - "(?:(?:LazyCompile|Function): [^ ]*(?: (?!native )[^ ]+:\\d+)?$)"); - - -/** - * @override - */ -devtools.profiler.JsProfile.prototype.skipThisFunction = function(name) -{ - return !devtools.profiler.JsProfile.JS_NON_NATIVE_RE.test(name); -}; - - -/** - * Profiler processor. Consumes profiler log and builds profile views. - * FIXME: change field naming style to use trailing underscore. - * - * @param {function(devtools.profiler.ProfileView)} newProfileCallback Callback - * that receives a new processed profile. - * @constructor - */ -devtools.profiler.Processor = function() -{ - var dispatches = { - "code-creation": { - parsers: [null, this.createAddressParser("code"), parseInt, null], - processor: this.processCodeCreation_, backrefs: true, - needsProfile: true }, - "code-move": { parsers: [this.createAddressParser("code"), - this.createAddressParser("code-move-to")], - processor: this.processCodeMove_, backrefs: true, - needsProfile: true }, - "code-delete": { parsers: [this.createAddressParser("code")], - processor: this.processCodeDelete_, backrefs: true, - needsProfile: true }, - "function-creation": { parsers: [this.createAddressParser("code"), - this.createAddressParser("function-obj")], - processor: this.processFunctionCreation_, backrefs: true }, - "function-move": { parsers: [this.createAddressParser("code"), - this.createAddressParser("code-move-to")], - processor: this.processFunctionMove_, backrefs: true }, - "function-delete": { parsers: [this.createAddressParser("code")], - processor: this.processFunctionDelete_, backrefs: true }, - "tick": { parsers: [this.createAddressParser("code"), - this.createAddressParser("stack"), parseInt, "var-args"], - processor: this.processTick_, backrefs: true, needProfile: true }, - "profiler": { parsers: [null, "var-args"], - processor: this.processProfiler_, needsProfile: false }, - "heap-sample-begin": { parsers: [null, null, parseInt], - processor: this.processHeapSampleBegin_ }, - "heap-sample-stats": { parsers: [null, null, parseInt, parseInt], - processor: this.processHeapSampleStats_ }, - "heap-sample-item": { parsers: [null, parseInt, parseInt], - processor: this.processHeapSampleItem_ }, - "heap-js-cons-item": { parsers: [null, parseInt, parseInt], - processor: this.processHeapJsConsItem_ }, - "heap-js-ret-item": { parsers: [null, "var-args"], - processor: this.processHeapJsRetItem_ }, - "heap-sample-end": { parsers: [null, null], - processor: this.processHeapSampleEnd_ }, - // Not used in DevTools Profiler. - "shared-library": null, - // Obsolete row types. - "code-allocate": null, - "begin-code-region": null, - "end-code-region": null}; - - if (devtools.profiler.Profile.VERSION === 2) { - dispatches["tick"] = { parsers: [this.createAddressParser("code"), - this.createAddressParser("stack"), - this.createAddressParser("func"), parseInt, "var-args"], - processor: this.processTickV2_, backrefs: true }; - } - - devtools.profiler.LogReader.call(this, dispatches); - - /** - * Callback that is called when a new profile is encountered in the log. - * @type {function()} - */ - this.startedProfileProcessing_ = null; - - /** - * Callback that is called periodically to display processing status. - * @type {function()} - */ - this.profileProcessingStatus_ = null; - - /** - * Callback that is called when a profile has been processed and is ready - * to be shown. - * @type {function(devtools.profiler.ProfileView)} - */ - this.finishedProfileProcessing_ = null; - - /** - * The current profile. - * @type {devtools.profiler.JsProfile} - */ - this.currentProfile_ = null; - - /** - * Builder of profile views. Created during "profiler,begin" event processing. - * @type {devtools.profiler.WebKitViewBuilder} - */ - this.viewBuilder_ = null; - - /** - * Next profile id. - * @type {number} - */ - this.profileId_ = 1; - - /** - * Counter for processed ticks. - * @type {number} - */ - this.ticksCount_ = 0; - - /** - * Interval id for updating processing status. - * @type {number} - */ - this.processingInterval_ = null; - - /** - * The current heap snapshot. - * @type {string} - */ - this.currentHeapSnapshot_ = null; - - /** - * Next heap snapshot id. - * @type {number} - */ - this.heapSnapshotId_ = 1; -}; -devtools.profiler.Processor.prototype.__proto__ = devtools.profiler.LogReader.prototype; - - -/** - * @override - */ -devtools.profiler.Processor.prototype.printError = function(str) -{ - debugPrint(str); -}; - - -/** - * @override - */ -devtools.profiler.Processor.prototype.skipDispatch = function(dispatch) -{ - return dispatch.needsProfile && this.currentProfile_ === null; -}; - - -/** - * Sets profile processing callbacks. - * - * @param {function()} started Started processing callback. - * @param {function(devtools.profiler.ProfileView)} finished Finished - * processing callback. - */ -devtools.profiler.Processor.prototype.setCallbacks = function(started, processing, finished) -{ - this.startedProfileProcessing_ = started; - this.profileProcessingStatus_ = processing; - this.finishedProfileProcessing_ = finished; -}; - - -/** - * 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; -/** - * @type {string} - */ -devtools.profiler.Processor.PROGRAM_ENTRY_STR = "0xffff"; - - -/** - * Sets new profile callback. - * @param {function(devtools.profiler.ProfileView)} callback Callback function. - */ -devtools.profiler.Processor.prototype.setNewProfileCallback = function(callback) -{ - this.newProfileCallback_ = callback; -}; - - -devtools.profiler.Processor.prototype.processProfiler_ = function(state, params) -{ - switch (state) { - case "resume": - if (this.currentProfile_ === null) { - this.currentProfile_ = new devtools.profiler.JsProfile(); - // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY - this.currentProfile_.addCode("Function", "(program)", devtools.profiler.Processor.PROGRAM_ENTRY, 1); - if (this.startedProfileProcessing_) - this.startedProfileProcessing_(); - this.ticksCount_ = 0; - var self = this; - if (this.profileProcessingStatus_) { - this.processingInterval_ = window.setInterval( - function() { self.profileProcessingStatus_(self.ticksCount_); }, - 1000); - } - } - break; - case "pause": - if (this.currentProfile_ !== null) { - window.clearInterval(this.processingInterval_); - this.processingInterval_ = null; - if (this.finishedProfileProcessing_) - this.finishedProfileProcessing_(this.createProfileForView()); - this.currentProfile_ = null; - } - break; - case "begin": - var samplingRate = NaN; - if (params.length > 0) - samplingRate = parseInt(params[0]); - if (isNaN(samplingRate)) - samplingRate = 1; - this.viewBuilder_ = new devtools.profiler.WebKitViewBuilder(samplingRate); - break; - // These events are valid but aren't used. - case "compression": - case "end": break; - default: - throw new Error("unknown profiler state: " + state); - } -}; - - -devtools.profiler.Processor.prototype.processCodeCreation_ = function(type, start, size, name) -{ - this.currentProfile_.addCode(this.expandAlias(type), name, start, size); -}; - - -devtools.profiler.Processor.prototype.processCodeMove_ = function(from, to) -{ - this.currentProfile_.moveCode(from, to); -}; - - -devtools.profiler.Processor.prototype.processCodeDelete_ = function(start) -{ - this.currentProfile_.deleteCode(start); -}; - - -devtools.profiler.Processor.prototype.processFunctionCreation_ = function(functionAddr, codeAddr) -{ - this.currentProfile_.addCodeAlias(functionAddr, codeAddr); -}; - - -devtools.profiler.Processor.prototype.processFunctionMove_ = function(from, to) -{ - this.currentProfile_.safeMoveDynamicCode(from, to); -}; - - -devtools.profiler.Processor.prototype.processFunctionDelete_ = function(start) -{ - this.currentProfile_.safeDeleteDynamicCode(start); -}; - - -// TODO(mnaganov): Remove after next V8 roll. -devtools.profiler.Processor.prototype.processTick_ = function(pc, sp, vmState, stack) -{ - // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY - stack.push(devtools.profiler.Processor.PROGRAM_ENTRY_STR); - this.currentProfile_.recordTick(this.processStack(pc, stack)); - this.ticksCount_++; -}; - - -devtools.profiler.Processor.prototype.processTickV2_ = function(pc, sp, func, vmState, stack) -{ - // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY - stack.push(devtools.profiler.Processor.PROGRAM_ENTRY_STR); - - - if (func) { - var funcEntry = this.currentProfile_.findEntry(func); - if (!funcEntry || !funcEntry.isJSFunction || !funcEntry.isJSFunction()) - func = 0; - else { - var currEntry = this.currentProfile_.findEntry(pc); - if (!currEntry || !currEntry.isJSFunction || currEntry.isJSFunction()) { - func = 0; - } - } - } - - this.currentProfile_.recordTick(this.processStack(pc, func, stack)); - this.ticksCount_++; -}; - - -devtools.profiler.Processor.prototype.processHeapSampleBegin_ = function(space, state, ticks) -{ - if (space !== "Heap") return; - this.currentHeapSnapshot_ = { - number: this.heapSnapshotId_++, - entries: {}, - clusters: {}, - lowlevels: {}, - ticks: ticks - }; -}; - - -devtools.profiler.Processor.prototype.processHeapSampleStats_ = function(space, state, capacity, used) -{ - if (space !== "Heap") return; -}; - - -devtools.profiler.Processor.prototype.processHeapSampleItem_ = function(item, number, size) -{ - if (!this.currentHeapSnapshot_) return; - this.currentHeapSnapshot_.lowlevels[item] = { - type: item, count: number, size: size - }; -}; - - -devtools.profiler.Processor.prototype.processHeapJsConsItem_ = function(item, number, size) -{ - if (!this.currentHeapSnapshot_) return; - this.currentHeapSnapshot_.entries[item] = { - cons: item, count: number, size: size, retainers: {} - }; -}; - - -devtools.profiler.Processor.prototype.processHeapJsRetItem_ = function(item, retainersArray) -{ - if (!this.currentHeapSnapshot_) return; - var rawRetainers = {}; - for (var i = 0, n = retainersArray.length; i < n; ++i) { - var entry = retainersArray[i].split(";"); - rawRetainers[entry[0]] = parseInt(entry[1], 10); - } - - function mergeRetainers(entry) { - for (var rawRetainer in rawRetainers) { - var consName = rawRetainer.indexOf(":") !== -1 ? rawRetainer.split(":")[0] : rawRetainer; - if (!(consName in entry.retainers)) - entry.retainers[consName] = { cons: consName, count: 0, clusters: {} }; - var retainer = entry.retainers[consName]; - retainer.count += rawRetainers[rawRetainer]; - if (consName !== rawRetainer) - retainer.clusters[rawRetainer] = true; - } - } - - if (item.indexOf(":") !== -1) { - // Array, Function, or Object instances cluster case. - if (!(item in this.currentHeapSnapshot_.clusters)) { - this.currentHeapSnapshot_.clusters[item] = { - cons: item, retainers: {} - }; - } - mergeRetainers(this.currentHeapSnapshot_.clusters[item]); - item = item.split(":")[0]; - } - mergeRetainers(this.currentHeapSnapshot_.entries[item]); -}; - - -devtools.profiler.Processor.prototype.processHeapSampleEnd_ = function(space, state) -{ - if (space !== "Heap") return; - var snapshot = this.currentHeapSnapshot_; - this.currentHeapSnapshot_ = null; - WebInspector.panels.profiles.addSnapshot(snapshot); -}; - - -/** - * Creates a profile for further displaying in ProfileView. - */ -devtools.profiler.Processor.prototype.createProfileForView = function() -{ - var profile = this.viewBuilder_.buildView(this.currentProfile_.getTopDownProfile()); - profile.uid = this.profileId_++; - profile.title = UserInitiatedProfileName + "." + profile.uid; - return profile; -}; |