summaryrefslogtreecommitdiff
path: root/Source/WebInspectorUI/UserInterface/Models/ProfileNode.js
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebInspectorUI/UserInterface/Models/ProfileNode.js
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Models/ProfileNode.js')
-rw-r--r--Source/WebInspectorUI/UserInterface/Models/ProfileNode.js278
1 files changed, 278 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Models/ProfileNode.js b/Source/WebInspectorUI/UserInterface/Models/ProfileNode.js
new file mode 100644
index 000000000..e6e952245
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/Models/ProfileNode.js
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2014 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+ */
+
+WebInspector.ProfileNode = class ProfileNode extends WebInspector.Object
+{
+ constructor(id, type, functionName, sourceCodeLocation, callInfo, calls, childNodes)
+ {
+ super();
+
+ childNodes = childNodes || [];
+
+ console.assert(id);
+ console.assert(!calls || calls instanceof Array);
+ console.assert(!calls || calls.length >= 1);
+ console.assert(!calls || calls.every((call) => call instanceof WebInspector.ProfileNodeCall));
+ console.assert(childNodes instanceof Array);
+ console.assert(childNodes.every((node) => node instanceof WebInspector.ProfileNode));
+
+ this._id = id;
+ this._type = type || WebInspector.ProfileNode.Type.Function;
+ this._functionName = functionName || null;
+ this._sourceCodeLocation = sourceCodeLocation || null;
+ this._calls = calls || null;
+ this._callInfo = callInfo || null;
+ this._childNodes = childNodes;
+ this._parentNode = null;
+ this._previousSibling = null;
+ this._nextSibling = null;
+ this._computedTotalTimes = false;
+
+ if (this._callInfo) {
+ this._startTime = this._callInfo.startTime;
+ this._endTime = this._callInfo.endTime;
+ this._totalTime = this._callInfo.totalTime;
+ this._callCount = this._callInfo.callCount;
+ }
+
+ for (var i = 0; i < this._childNodes.length; ++i)
+ this._childNodes[i].establishRelationships(this, this._childNodes[i - 1], this._childNodes[i + 1]);
+
+ if (this._calls) {
+ for (var i = 0; i < this._calls.length; ++i)
+ this._calls[i].establishRelationships(this, this._calls[i - 1], this._calls[i + 1]);
+ }
+ }
+
+ // Public
+
+ get id()
+ {
+ return this._id;
+ }
+
+ get type()
+ {
+ return this._type;
+ }
+
+ get functionName()
+ {
+ return this._functionName;
+ }
+
+ get sourceCodeLocation()
+ {
+ return this._sourceCodeLocation;
+ }
+
+ get startTime()
+ {
+ if (this._startTime === undefined)
+ this._startTime = Math.max(0, this._calls[0].startTime);
+ return this._startTime;
+ }
+
+ get endTime()
+ {
+ if (this._endTime === undefined)
+ this._endTime = Math.min(this._calls.lastValue.endTime, Infinity);
+ return this._endTime;
+ }
+
+ get selfTime()
+ {
+ this._computeTotalTimesIfNeeded();
+ return this._selfTime;
+ }
+
+ get totalTime()
+ {
+ this._computeTotalTimesIfNeeded();
+ return this._totalTime;
+ }
+
+ get callInfo()
+ {
+ return this._callInfo;
+ }
+
+ get calls()
+ {
+ return this._calls;
+ }
+
+ get previousSibling()
+ {
+ return this._previousSibling;
+ }
+
+ get nextSibling()
+ {
+ return this._nextSibling;
+ }
+
+ get parentNode()
+ {
+ return this._parentNode;
+ }
+
+ get childNodes()
+ {
+ return this._childNodes;
+ }
+
+ computeCallInfoForTimeRange(rangeStartTime, rangeEndTime)
+ {
+ console.assert(typeof rangeStartTime === "number");
+ console.assert(typeof rangeEndTime === "number");
+
+ // With aggregate call info we can't accurately partition self/total/average time
+ // in partial ranges because we don't know exactly when each call started. So we
+ // always return the entire range.
+ if (this._callInfo) {
+ if (this._selfTime === undefined) {
+ var childNodesTotalTime = 0;
+ for (var childNode of this._childNodes)
+ childNodesTotalTime += childNode.totalTime;
+ this._selfTime = this._totalTime - childNodesTotalTime;
+ // selfTime can negative or very close to zero due to floating point error.
+ // Since we show at most four decimal places, treat anything less as zero.
+ if (this._selfTime < 0.0001)
+ this._selfTime = 0.0;
+ }
+
+ return {
+ callCount: this._callCount,
+ startTime: this._startTime,
+ endTime: this._endTime,
+ selfTime: this._selfTime,
+ totalTime: this._totalTime,
+ averageTime: (this._selfTime / this._callCount),
+ };
+ }
+
+ // COMPATIBILITY (iOS 8): Profiles included per-call information and can be finely partitioned.
+ // Compute that below by iterating over all the calls / children for the time range.
+
+ var recordCallCount = true;
+ var callCount = 0;
+
+ function totalTimeInRange(previousValue, call)
+ {
+ if (rangeStartTime > call.endTime || rangeEndTime < call.startTime)
+ return previousValue;
+
+ if (recordCallCount)
+ ++callCount;
+
+ return previousValue + Math.min(call.endTime, rangeEndTime) - Math.max(rangeStartTime, call.startTime);
+ }
+
+ var startTime = Math.max(rangeStartTime, this._calls[0].startTime);
+ var endTime = Math.min(this._calls.lastValue.endTime, rangeEndTime);
+ var totalTime = this._calls.reduce(totalTimeInRange, 0);
+
+ recordCallCount = false;
+
+ var childNodesTotalTime = 0;
+ for (var childNode of this._childNodes)
+ childNodesTotalTime += childNode.calls.reduce(totalTimeInRange, 0);
+
+ var selfTime = totalTime - childNodesTotalTime;
+ var averageTime = selfTime / callCount;
+
+ return {startTime, endTime, totalTime, selfTime, callCount, averageTime};
+ }
+
+ traverseNextProfileNode(stayWithin)
+ {
+ var profileNode = this._childNodes[0];
+ if (profileNode)
+ return profileNode;
+
+ if (this === stayWithin)
+ return null;
+
+ profileNode = this._nextSibling;
+ if (profileNode)
+ return profileNode;
+
+ profileNode = this;
+ while (profileNode && !profileNode.nextSibling && profileNode.parentNode !== stayWithin)
+ profileNode = profileNode.parentNode;
+
+ if (!profileNode)
+ return null;
+
+ return profileNode.nextSibling;
+ }
+
+ saveIdentityToCookie(cookie)
+ {
+ cookie[WebInspector.ProfileNode.TypeCookieKey] = this._type || null;
+ cookie[WebInspector.ProfileNode.FunctionNameCookieKey] = this._functionName || null;
+ cookie[WebInspector.ProfileNode.SourceCodeURLCookieKey] = this._sourceCodeLocation ? this._sourceCodeLocation.sourceCode.url ? this._sourceCodeLocation.sourceCode.url.hash : null : null;
+ cookie[WebInspector.ProfileNode.SourceCodeLocationLineCookieKey] = this._sourceCodeLocation ? this._sourceCodeLocation.lineNumber : null;
+ cookie[WebInspector.ProfileNode.SourceCodeLocationColumnCookieKey] = this._sourceCodeLocation ? this._sourceCodeLocation.columnNumber : null;
+ }
+
+ // Protected
+
+ establishRelationships(parentNode, previousSibling, nextSibling)
+ {
+ this._parentNode = parentNode || null;
+ this._previousSibling = previousSibling || null;
+ this._nextSibling = nextSibling || null;
+ }
+
+ // Private
+
+ _computeTotalTimesIfNeeded()
+ {
+ if (this._computedTotalTimes)
+ return;
+
+ this._computedTotalTimes = true;
+
+ var info = this.computeCallInfoForTimeRange(0, Infinity);
+ this._startTime = info.startTime;
+ this._endTime = info.endTime;
+ this._selfTime = info.selfTime;
+ this._totalTime = info.totalTime;
+ }
+};
+
+WebInspector.ProfileNode.Type = {
+ Function: "profile-node-type-function",
+ Program: "profile-node-type-program"
+};
+
+WebInspector.ProfileNode.TypeIdentifier = "profile-node";
+WebInspector.ProfileNode.TypeCookieKey = "profile-node-type";
+WebInspector.ProfileNode.FunctionNameCookieKey = "profile-node-function-name";
+WebInspector.ProfileNode.SourceCodeURLCookieKey = "profile-node-source-code-url";
+WebInspector.ProfileNode.SourceCodeLocationLineCookieKey = "profile-node-source-code-location-line";
+WebInspector.ProfileNode.SourceCodeLocationColumnCookieKey = "profile-node-source-code-location-column";