<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[186218] trunk/Source</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/186218">186218</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-07-01 21:46:43 -0700 (Wed, 01 Jul 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Web Inspector: Aggregate profile call information on the backend to drastically reduce profile sizes
https://bugs.webkit.org/show_bug.cgi?id=146536
Patch by Joseph Pecoraro <pecoraro@apple.com> on 2015-07-01
Reviewed by Timothy Hatcher.
Source/JavaScriptCore:
* inspector/protocol/Timeline.json:
Change a CPUProfile from sending a required "calls" param to sending a required
"callInfo" param which includes aggregated information about the calls.
Source/WebCore:
* inspector/TimelineRecordFactory.cpp:
(WebCore::buildAggregateCallInfoInspectorObject):
(WebCore::buildInspectorObject):
Replace the array of Call objects with a single aggregated call info object.
Source/WebInspectorUI:
Since we still support legacy backends, the frontend documents where
it is handling legacy backends with compatibility comments.
* UserInterface/Models/ProfileNode.js:
(WebInspector.ProfileNode):
(WebInspector.ProfileNode.prototype.get callInfo):
Handle a ProfileNode created with callInfo or calls. They are mutually exclusive.
* UserInterface/Models/ScriptTimelineRecord.js:
(WebInspector.ScriptTimelineRecord.prototype._initializeProfileFromPayload.profileNodeFromPayload):
If the profile has per-call information, construct ProfileNodeCall objects, otherwise
just construct the ProfileNode with the aggregate callInfo value.
* UserInterface/Views/ScriptTimelineDataGridNode.js:
(WebInspector.ScriptTimelineDataGridNode.prototype.get data):
When we have aggregate call information we cannot easily partition a script,
so we instead treat the entire script as one large atomic unit in the timeline.
If the timeline range has any portion of the script, show the entire script.
Users used to be able to select a portion of a script and view the relevant
functions called in just that sliver, but this doesn't appear to be a well
known feature or commonly used. In fact, given the small ranges of time it
could be confusing for users.
* UserInterface/Views/TimelineRecordingContentView.js:
(WebInspector.TimelineRecordingContentView.prototype.matchTreeElementAgainstCustomFilters):
Treat as a discrete unit.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorprotocolTimelinejson">trunk/Source/JavaScriptCore/inspector/protocol/Timeline.json</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreinspectorTimelineRecordFactorycpp">trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsProfileNodejs">trunk/Source/WebInspectorUI/UserInterface/Models/ProfileNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsScriptTimelineRecordjs">trunk/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsScriptTimelineDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTimelineRecordingContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (186217 => 186218)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-07-02 04:30:53 UTC (rev 186217)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-07-02 04:46:43 UTC (rev 186218)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2015-07-01 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Aggregate profile call information on the backend to drastically reduce profile sizes
+ https://bugs.webkit.org/show_bug.cgi?id=146536
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/protocol/Timeline.json:
+ Change a CPUProfile from sending a required "calls" param to sending a required
+ "callInfo" param which includes aggregated information about the calls.
+
</ins><span class="cx"> 2015-06-30 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> DFG::freezeFragile should register the frozen value's structure
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolTimelinejson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/Timeline.json (186217 => 186218)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/Timeline.json        2015-07-02 04:30:53 UTC (rev 186217)
+++ trunk/Source/JavaScriptCore/inspector/protocol/Timeline.json        2015-07-02 04:46:43 UTC (rev 186218)
</span><span class="lines">@@ -53,12 +53,14 @@
</span><span class="cx"> "description": "Timeline record contains information about the recorded activity."
</span><span class="cx"> },
</span><span class="cx"> {
</span><del>- "id": "CPUProfileNodeCall",
</del><ins>+ "id": "CPUProfileNodeAggregateCallInfo",
</ins><span class="cx"> "type": "object",
</span><del>- "description": "CPU Profile call info. Holds time information for a specific call that happened on a node.",
</del><ins>+ "description": "Aggregate CPU Profile call info. Holds time information for all the calls that happened on a node.",
</ins><span class="cx"> "properties": [
</span><del>- { "name": "startTime", "type": "number", "description": "Start time for the call." },
- { "name": "totalTime", "type": "number", "description": "Total execution time for the call." }
</del><ins>+ { "name": "callCount", "type": "number", "description": "Total number of calls." },
+ { "name": "startTime", "type": "number", "description": "Start time for the first call." },
+ { "name": "endTime", "type": "number", "description": "End time for the last call." },
+ { "name": "totalTime", "type": "number", "description": "Total execution time for all calls combined." }
</ins><span class="cx"> ]
</span><span class="cx"> },
</span><span class="cx"> {
</span><span class="lines">@@ -67,7 +69,7 @@
</span><span class="cx"> "description": "CPU Profile node. Holds callsite information, execution statistics and child nodes.",
</span><span class="cx"> "properties": [
</span><span class="cx"> { "name": "id", "type": "integer", "description": "Unique identifier for this call site." },
</span><del>- { "name": "calls", "type": "array", "items": { "$ref": "CPUProfileNodeCall" }, "description": "Calls making up this node." },
</del><ins>+ { "name": "callInfo", "$ref": "CPUProfileNodeAggregateCallInfo", "description": "Aggregate info about all the calls that making up this node." },
</ins><span class="cx"> { "name": "functionName", "type": "string", "optional": true, "description": "Function name." },
</span><span class="cx"> { "name": "url", "type": "string", "optional": true, "description": "URL." },
</span><span class="cx"> { "name": "lineNumber", "type": "integer", "optional": true, "description": "Line number." },
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (186217 => 186218)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-07-02 04:30:53 UTC (rev 186217)
+++ trunk/Source/WebCore/ChangeLog        2015-07-02 04:46:43 UTC (rev 186218)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2015-07-01 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Aggregate profile call information on the backend to drastically reduce profile sizes
+ https://bugs.webkit.org/show_bug.cgi?id=146536
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/TimelineRecordFactory.cpp:
+ (WebCore::buildAggregateCallInfoInspectorObject):
+ (WebCore::buildInspectorObject):
+ Replace the array of Call objects with a single aggregated call info object.
+
</ins><span class="cx"> 2015-07-01 Brent Fulgham <bfulgham@apple.com>
</span><span class="cx">
</span><span class="cx"> [Win] REGRESSION (r185124) CACFLayer handling broken
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorTimelineRecordFactorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp (186217 => 186218)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp        2015-07-02 04:30:53 UTC (rev 186217)
+++ trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp        2015-07-02 04:46:43 UTC (rev 186218)
</span><span class="lines">@@ -209,23 +209,28 @@
</span><span class="cx"> data->setArray("root", createQuad(quad));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static Ref<Protocol::Timeline::CPUProfileNodeCall> buildInspectorObject(const JSC::ProfileNode::Call& call)
</del><ins>+static Ref<Protocol::Timeline::CPUProfileNodeAggregateCallInfo> buildAggregateCallInfoInspectorObject(const JSC::ProfileNode* node)
</ins><span class="cx"> {
</span><del>- return Protocol::Timeline::CPUProfileNodeCall::create()
- .setStartTime(call.startTime())
- .setTotalTime(call.elapsedTime())
</del><ins>+ double startTime = node->calls()[0].startTime();
+ double endTime = node->calls().last().startTime() + node->calls().last().elapsedTime();
+
+ double totalTime = 0;
+ for (const JSC::ProfileNode::Call& call : node->calls())
+ totalTime += call.elapsedTime();
+
+ return Protocol::Timeline::CPUProfileNodeAggregateCallInfo::create()
+ .setCallCount(node->calls().size())
+ .setStartTime(startTime)
+ .setEndTime(endTime)
+ .setTotalTime(totalTime)
</ins><span class="cx"> .release();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static Ref<Protocol::Timeline::CPUProfileNode> buildInspectorObject(const JSC::ProfileNode* node)
</span><span class="cx"> {
</span><del>- auto calls = Protocol::Array<Protocol::Timeline::CPUProfileNodeCall>::create();
- for (const JSC::ProfileNode::Call& call : node->calls())
- calls->addItem(buildInspectorObject(call));
-
</del><span class="cx"> auto result = Protocol::Timeline::CPUProfileNode::create()
</span><span class="cx"> .setId(node->id())
</span><del>- .setCalls(WTF::move(calls))
</del><ins>+ .setCallInfo(buildAggregateCallInfoInspectorObject(node))
</ins><span class="cx"> .release();
</span><span class="cx">
</span><span class="cx"> if (!node->functionName().isEmpty())
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (186217 => 186218)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2015-07-02 04:30:53 UTC (rev 186217)
+++ trunk/Source/WebInspectorUI/ChangeLog        2015-07-02 04:46:43 UTC (rev 186218)
</span><span class="lines">@@ -1,3 +1,37 @@
</span><ins>+2015-07-01 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Aggregate profile call information on the backend to drastically reduce profile sizes
+ https://bugs.webkit.org/show_bug.cgi?id=146536
+
+ Reviewed by Timothy Hatcher.
+
+ Since we still support legacy backends, the frontend documents where
+ it is handling legacy backends with compatibility comments.
+
+ * UserInterface/Models/ProfileNode.js:
+ (WebInspector.ProfileNode):
+ (WebInspector.ProfileNode.prototype.get callInfo):
+ Handle a ProfileNode created with callInfo or calls. They are mutually exclusive.
+
+ * UserInterface/Models/ScriptTimelineRecord.js:
+ (WebInspector.ScriptTimelineRecord.prototype._initializeProfileFromPayload.profileNodeFromPayload):
+ If the profile has per-call information, construct ProfileNodeCall objects, otherwise
+ just construct the ProfileNode with the aggregate callInfo value.
+
+ * UserInterface/Views/ScriptTimelineDataGridNode.js:
+ (WebInspector.ScriptTimelineDataGridNode.prototype.get data):
+ When we have aggregate call information we cannot easily partition a script,
+ so we instead treat the entire script as one large atomic unit in the timeline.
+ If the timeline range has any portion of the script, show the entire script.
+ Users used to be able to select a portion of a script and view the relevant
+ functions called in just that sliver, but this doesn't appear to be a well
+ known feature or commonly used. In fact, given the small ranges of time it
+ could be confusing for users.
+
+ * UserInterface/Views/TimelineRecordingContentView.js:
+ (WebInspector.TimelineRecordingContentView.prototype.matchTreeElementAgainstCustomFilters):
+ Treat as a discrete unit.
+
</ins><span class="cx"> 2015-07-01 Devin Rousso <drousso@apple.com>
</span><span class="cx">
</span><span class="cx"> Web Inspector: When autocompleting, pressing tab twice shouldn't insert a tab character
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsProfileNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ProfileNode.js (186217 => 186218)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/ProfileNode.js        2015-07-02 04:30:53 UTC (rev 186217)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ProfileNode.js        2015-07-02 04:46:43 UTC (rev 186218)
</span><span class="lines">@@ -25,16 +25,16 @@
</span><span class="cx">
</span><span class="cx"> WebInspector.ProfileNode = class ProfileNode extends WebInspector.Object
</span><span class="cx"> {
</span><del>- constructor(id, type, functionName, sourceCodeLocation, calls, childNodes)
</del><ins>+ constructor(id, type, functionName, sourceCodeLocation, callInfo, calls, childNodes)
</ins><span class="cx"> {
</span><span class="cx"> super();
</span><span class="cx">
</span><span class="cx"> childNodes = childNodes || [];
</span><span class="cx">
</span><span class="cx"> console.assert(id);
</span><del>- console.assert(calls instanceof Array);
- console.assert(calls.length >= 1);
- console.assert(calls.every(function(call) { return call instanceof WebInspector.ProfileNodeCall; }));
</del><ins>+ console.assert(!calls || calls instanceof Array);
+ console.assert(!calls || calls.length >= 1);
+ console.assert(!calls || calls.every(function(call) { return call instanceof WebInspector.ProfileNodeCall; }));
</ins><span class="cx"> console.assert(childNodes instanceof Array);
</span><span class="cx"> console.assert(childNodes.every(function(node) { return node instanceof WebInspector.ProfileNode; }));
</span><span class="cx">
</span><span class="lines">@@ -42,18 +42,28 @@
</span><span class="cx"> this._type = type || WebInspector.ProfileNode.Type.Function;
</span><span class="cx"> this._functionName = functionName || null;
</span><span class="cx"> this._sourceCodeLocation = sourceCodeLocation || null;
</span><del>- this._calls = calls;
</del><ins>+ this._calls = calls || null;
+ this._callInfo = callInfo || null;
</ins><span class="cx"> this._childNodes = childNodes;
</span><span class="cx"> this._parentNode = null;
</span><span class="cx"> this._previousSibling = null;
</span><span class="cx"> this._nextSibling = null;
</span><span class="cx"> this._computedTotalTimes = false;
</span><span class="cx">
</span><ins>+ if (this._callInfo) {
+ this._startTime = this._callInfo.startTime;
+ this._endTime = this._callInfo.endTime;
+ this._totalTime = this._callInfo.totalTime;
+ this._callCount = this._callInfo.callCount;
+ }
+
</ins><span class="cx"> for (var i = 0; i < this._childNodes.length; ++i)
</span><span class="cx"> this._childNodes[i].establishRelationships(this, this._childNodes[i - 1], this._childNodes[i + 1]);
</span><span class="cx">
</span><del>- for (var i = 0; i < this._calls.length; ++i)
- this._calls[i].establishRelationships(this, this._calls[i - 1], this._calls[i + 1]);
</del><ins>+ 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]);
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Public
</span><span class="lines">@@ -104,6 +114,11 @@
</span><span class="cx"> return this._totalTime;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ get callInfo()
+ {
+ return this._callInfo;
+ }
+
</ins><span class="cx"> get calls()
</span><span class="cx"> {
</span><span class="cx"> return this._calls;
</span><span class="lines">@@ -134,6 +149,30 @@
</span><span class="cx"> console.assert(typeof rangeStartTime === "number");
</span><span class="cx"> console.assert(typeof rangeEndTime === "number");
</span><span class="cx">
</span><ins>+ // 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;
+ }
+
+ return {
+ callCount: this._callCount,
+ startTime: this._startTime,
+ endTime: this._endTime,
+ selfTime: this._selfTime,
+ totalTime: this._totalTime,
+ averageTime: (this._selfTime / this._callCount),
+ };
+ }
+
+ // COMPATIBILITY (iOS8): Profiles included per-call information and can be finely partitioned.
+ // Compute that below by iterating over all the calls / children for the time range.
+
</ins><span class="cx"> var recordCallCount = true;
</span><span class="cx"> var callCount = 0;
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsScriptTimelineRecordjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js (186217 => 186218)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js        2015-07-02 04:30:53 UTC (rev 186217)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js        2015-07-02 04:46:43 UTC (rev 186218)
</span><span class="lines">@@ -74,14 +74,13 @@
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> var payload = this._profilePayload;
</span><del>- delete this._profilePayload;
</del><ins>+ this._profilePayload = undefined;
</ins><span class="cx">
</span><span class="cx"> console.assert(payload.rootNodes instanceof Array);
</span><span class="cx">
</span><span class="cx"> function profileNodeFromPayload(nodePayload)
</span><span class="cx"> {
</span><span class="cx"> console.assert("id" in nodePayload);
</span><del>- console.assert(nodePayload.calls instanceof Array);
</del><span class="cx">
</span><span class="cx"> if (nodePayload.url) {
</span><span class="cx"> var sourceCode = WebInspector.frameResourceManager.resourceForURL(nodePayload.url);
</span><span class="lines">@@ -99,9 +98,16 @@
</span><span class="cx">
</span><span class="cx"> var type = isProgramCode ? WebInspector.ProfileNode.Type.Program : WebInspector.ProfileNode.Type.Function;
</span><span class="cx"> var functionName = !isProgramCode && !isAnonymousFunction && nodePayload.functionName !== "(unknown)" ? nodePayload.functionName : null;
</span><del>- var calls = nodePayload.calls.map(profileNodeCallFromPayload);
</del><span class="cx">
</span><del>- return new WebInspector.ProfileNode(nodePayload.id, type, functionName, sourceCodeLocation, calls, nodePayload.children);
</del><ins>+ // COMPATIBILITY (iOS8): Timeline.CPUProfileNodes used to include an array of complete
+ // call information instead of the aggregated "callInfo" data.
+ var calls = null;
+ if ("calls" in nodePayload) {
+ console.assert(nodePayload.calls instanceof Array);
+ calls = nodePayload.calls.map(profileNodeCallFromPayload);
+ }
+
+ return new WebInspector.ProfileNode(nodePayload.id, type, functionName, sourceCodeLocation, nodePayload.callInfo, calls, nodePayload.children);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> function profileNodeCallFromPayload(nodeCallPayload)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsScriptTimelineDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js (186217 => 186218)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js        2015-07-02 04:30:53 UTC (rev 186217)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js        2015-07-02 04:46:43 UTC (rev 186218)
</span><span class="lines">@@ -71,10 +71,19 @@
</span><span class="cx">
</span><span class="cx"> get data()
</span><span class="cx"> {
</span><del>- var startTime = Math.max(this._rangeStartTime, this._record.startTime);
- var duration = Math.min(this._record.startTime + this._record.duration, this._rangeEndTime) - startTime;
</del><ins>+ var startTime = this._record.startTime;
+ var duration = this._record.startTime + this._record.duration - startTime;
</ins><span class="cx"> var callFrameOrSourceCodeLocation = this._record.initiatorCallFrame || this._record.sourceCodeLocation;
</span><span class="cx">
</span><ins>+ // COMPATIBILITY (iOS8): Profiles included per-call information and can be finely partitioned.
+ if (this._record.profile) {
+ var oneRootNode = this._record.profile.topDownRootNodes[0];
+ if (oneRootNode && oneRootNode.calls) {
+ startTime = Math.max(this._rangeStartTime, this._record.startTime);
+ duration = Math.min(this._record.startTime + this._record.duration, this._rangeEndTime) - startTime;
+ }
+ }
+
</ins><span class="cx"> return {eventType: this._record.eventType, startTime, selfTime: duration, totalTime: duration,
</span><span class="cx"> averageTime: duration, callCount: 1, location: callFrameOrSourceCodeLocation};
</span><span class="cx"> },
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTimelineRecordingContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js (186217 => 186218)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js        2015-07-02 04:30:53 UTC (rev 186217)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js        2015-07-02 04:46:43 UTC (rev 186218)
</span><span class="lines">@@ -308,10 +308,8 @@
</span><span class="cx">
</span><span class="cx"> if (treeElement instanceof WebInspector.ProfileNodeTreeElement) {
</span><span class="cx"> var profileNode = treeElement.profileNode;
</span><del>- for (var call of profileNode.calls) {
- if (checkTimeBounds(call.startTime, call.endTime))
- return true;
- }
</del><ins>+ if (checkTimeBounds(profileNode.startTime, profileNode.endTime))
+ return true;
</ins><span class="cx">
</span><span class="cx"> return false;
</span><span class="cx"> }
</span></span></pre>
</div>
</div>
</body>
</html>