Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(174)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/timeline/TimelineJSProfile.js

Issue 1666563005: DevTools: merge ScriptCallStack and ScriptAsyncCallStack, move CallStacks from console to Runtime. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 5
6 WebInspector.TimelineJSProfileProcessor = { }; 6 WebInspector.TimelineJSProfileProcessor = { };
7 7
8 /** 8 /**
9 * @param {!ProfilerAgent.CPUProfile} jsProfile 9 * @param {!ProfilerAgent.CPUProfile} jsProfile
10 * @param {!WebInspector.TracingModel.Thread} thread 10 * @param {!WebInspector.TracingModel.Thread} thread
11 * @return {!Array<!WebInspector.TracingModel.Event>} 11 * @return {!Array<!WebInspector.TracingModel.Event>}
12 */ 12 */
13 WebInspector.TimelineJSProfileProcessor.generateTracingEventsFromCpuProfile = fu nction(jsProfile, thread) 13 WebInspector.TimelineJSProfileProcessor.generateTracingEventsFromCpuProfile = fu nction(jsProfile, thread)
14 { 14 {
15 if (!jsProfile.samples) 15 if (!jsProfile.samples)
16 return []; 16 return [];
17 var jsProfileModel = new WebInspector.CPUProfileDataModel(jsProfile); 17 var jsProfileModel = new WebInspector.CPUProfileDataModel(jsProfile);
18 var idleNode = jsProfileModel.idleNode; 18 var idleNode = jsProfileModel.idleNode;
19 var programNode = jsProfileModel.programNode; 19 var programNode = jsProfileModel.programNode;
20 var gcNode = jsProfileModel.gcNode; 20 var gcNode = jsProfileModel.gcNode;
21 var samples = jsProfileModel.samples; 21 var samples = jsProfileModel.samples;
22 var timestamps = jsProfileModel.timestamps; 22 var timestamps = jsProfileModel.timestamps;
23 var jsEvents = []; 23 var jsEvents = [];
24 /** @type {!Map<!Object, !ConsoleAgent.StackTrace>} */ 24 /** @type {!Map<!Object, !Array<!RuntimeAgent.CallFrame>>} */
25 var nodeToStackMap = new Map(); 25 var nodeToStackMap = new Map();
26 nodeToStackMap.set(programNode, []); 26 nodeToStackMap.set(programNode, []);
27 for (var i = 0; i < samples.length; ++i) { 27 for (var i = 0; i < samples.length; ++i) {
28 var node = jsProfileModel.nodeByIndex(i); 28 var node = jsProfileModel.nodeByIndex(i);
29 if (node === gcNode || node === idleNode) 29 if (node === gcNode || node === idleNode)
30 continue; 30 continue;
31 var stackTrace = nodeToStackMap.get(node); 31 var callFrames = nodeToStackMap.get(node);
32 if (!stackTrace) { 32 if (!callFrames) {
33 stackTrace = /** @type {!ConsoleAgent.StackTrace} */ (new Array(node .depth + 1)); 33 callFrames = /** @type {!Array<!RuntimeAgent.CallFrame>} */ (new Arr ay(node.depth + 1));
34 nodeToStackMap.set(node, stackTrace); 34 nodeToStackMap.set(node, callFrames);
35 for (var j = 0; node.parent; node = node.parent) 35 for (var j = 0; node.parent; node = node.parent)
36 stackTrace[j++] = /** @type {!ConsoleAgent.CallFrame} */ (node); 36 callFrames[j++] = /** @type {!RuntimeAgent.CallFrame} */ (node);
37 } 37 }
38 var jsSampleEvent = new WebInspector.TracingModel.Event(WebInspector.Tra cingModel.DevToolsTimelineEventCategory, 38 var jsSampleEvent = new WebInspector.TracingModel.Event(WebInspector.Tra cingModel.DevToolsTimelineEventCategory,
39 WebInspector.TimelineModel.RecordType.JSSample, 39 WebInspector.TimelineModel.RecordType.JSSample,
40 WebInspector.TracingModel.Phase.Instant, timestamps[i], thread); 40 WebInspector.TracingModel.Phase.Instant, timestamps[i], thread);
41 jsSampleEvent.args["data"] = { stackTrace: stackTrace }; 41 jsSampleEvent.args["data"] = { stackTrace: callFrames };
42 jsEvents.push(jsSampleEvent); 42 jsEvents.push(jsSampleEvent);
43 } 43 }
44 return jsEvents; 44 return jsEvents;
45 } 45 }
46 46
47 /** 47 /**
48 * @param {!Array<!WebInspector.TracingModel.Event>} events 48 * @param {!Array<!WebInspector.TracingModel.Event>} events
49 * @return {!Array<!WebInspector.TracingModel.Event>} 49 * @return {!Array<!WebInspector.TracingModel.Event>}
50 */ 50 */
51 WebInspector.TimelineJSProfileProcessor.generateJSFrameEvents = function(events) 51 WebInspector.TimelineJSProfileProcessor.generateJSFrameEvents = function(events)
52 { 52 {
53 /** 53 /**
54 * @param {!ConsoleAgent.CallFrame} frame1 54 * @param {!RuntimeAgent.CallFrame} frame1
55 * @param {!ConsoleAgent.CallFrame} frame2 55 * @param {!RuntimeAgent.CallFrame} frame2
56 * @return {boolean} 56 * @return {boolean}
57 */ 57 */
58 function equalFrames(frame1, frame2) 58 function equalFrames(frame1, frame2)
59 { 59 {
60 return frame1.scriptId === frame2.scriptId && frame1.functionName === fr ame2.functionName; 60 return frame1.scriptId === frame2.scriptId && frame1.functionName === fr ame2.functionName;
61 } 61 }
62 62
63 /** 63 /**
64 * @param {!WebInspector.TracingModel.Event} e 64 * @param {!WebInspector.TracingModel.Event} e
65 * @return {number} 65 * @return {number}
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 } 159 }
160 var minFrameDurationMs = currentSamplingIntervalMs / 2; 160 var minFrameDurationMs = currentSamplingIntervalMs / 2;
161 for (var k = 0; k < depth; ++k) 161 for (var k = 0; k < depth; ++k)
162 jsFramesStack[k].setEndTime(time); 162 jsFramesStack[k].setEndTime(time);
163 for (var k = depth; k < jsFramesStack.length; ++k) 163 for (var k = depth; k < jsFramesStack.length; ++k)
164 jsFramesStack[k].setEndTime(Math.min(eventEndTime(jsFramesStack[k]) + minFrameDurationMs, time)); 164 jsFramesStack[k].setEndTime(Math.min(eventEndTime(jsFramesStack[k]) + minFrameDurationMs, time));
165 jsFramesStack.length = depth; 165 jsFramesStack.length = depth;
166 } 166 }
167 167
168 /** 168 /**
169 * @param {!Array<!ConsoleAgent.CallFrame>} stack 169 * @param {!Array<!RuntimeAgent.CallFrame>} stack
170 */ 170 */
171 function filterStackFrames(stack) 171 function filterStackFrames(stack)
172 { 172 {
173 for (var i = 0, j = 0; i < stack.length; ++i) { 173 for (var i = 0, j = 0; i < stack.length; ++i) {
174 var url = stack[i].url; 174 var url = stack[i].url;
175 if (url && url.startsWith("native ")) 175 if (url && url.startsWith("native "))
176 continue; 176 continue;
177 stack[j++] = stack[i]; 177 stack[j++] = stack[i];
178 } 178 }
179 stack.length = j; 179 stack.length = j;
180 } 180 }
181 181
182 /** 182 /**
183 * @param {!WebInspector.TracingModel.Event} e 183 * @param {!WebInspector.TracingModel.Event} e
184 */ 184 */
185 function extractStackTrace(e) 185 function extractStackTrace(e)
186 { 186 {
187 var recordTypes = WebInspector.TimelineModel.RecordType; 187 var recordTypes = WebInspector.TimelineModel.RecordType;
188 var stackTrace; 188 var callFrames;
189 if (e.name === recordTypes.JSSample) { 189 if (e.name === recordTypes.JSSample) {
190 var eventData = e.args["data"] || e.args["beginData"]; 190 var eventData = e.args["data"] || e.args["beginData"];
191 stackTrace = /** @type {!Array<!ConsoleAgent.CallFrame>} */ (eventDa ta && eventData["stackTrace"]); 191 callFrames = /** @type {!Array<!RuntimeAgent.CallFrame>} */ (eventDa ta && eventData["stackTrace"]);
192 } else { 192 } else {
193 stackTrace = /** @type {!Array<!ConsoleAgent.CallFrame>} */ (jsFrame sStack.map(frameEvent => frameEvent.args["data"]).reverse()); 193 callFrames = /** @type {!Array<!RuntimeAgent.CallFrame>} */ (jsFrame sStack.map(frameEvent => frameEvent.args["data"]).reverse());
194 } 194 }
195 if (filterNativeFunctions) 195 if (filterNativeFunctions)
196 filterStackFrames(stackTrace); 196 filterStackFrames(callFrames);
197 var endTime = eventEndTime(e); 197 var endTime = eventEndTime(e);
198 var numFrames = stackTrace.length; 198 var numFrames = callFrames.length;
199 var minFrames = Math.min(numFrames, jsFramesStack.length); 199 var minFrames = Math.min(numFrames, jsFramesStack.length);
200 var i; 200 var i;
201 for (i = lockedJsStackDepth.peekLast() || 0; i < minFrames; ++i) { 201 for (i = lockedJsStackDepth.peekLast() || 0; i < minFrames; ++i) {
202 var newFrame = stackTrace[numFrames - 1 - i]; 202 var newFrame = callFrames[numFrames - 1 - i];
203 var oldFrame = jsFramesStack[i].args["data"]; 203 var oldFrame = jsFramesStack[i].args["data"];
204 if (!equalFrames(newFrame, oldFrame)) 204 if (!equalFrames(newFrame, oldFrame))
205 break; 205 break;
206 jsFramesStack[i].setEndTime(Math.max(jsFramesStack[i].endTime, endTi me)); 206 jsFramesStack[i].setEndTime(Math.max(jsFramesStack[i].endTime, endTi me));
207 } 207 }
208 truncateJSStack(i, e.startTime); 208 truncateJSStack(i, e.startTime);
209 for (; i < numFrames; ++i) { 209 for (; i < numFrames; ++i) {
210 var frame = stackTrace[numFrames - 1 - i]; 210 var frame = callFrames[numFrames - 1 - i];
211 var jsFrameEvent = new WebInspector.TracingModel.Event(WebInspector. TracingModel.DevToolsTimelineEventCategory, recordTypes.JSFrame, 211 var jsFrameEvent = new WebInspector.TracingModel.Event(WebInspector. TracingModel.DevToolsTimelineEventCategory, recordTypes.JSFrame,
212 WebInspector.TracingModel.Phase.Complete, e.startTime, e.thread) ; 212 WebInspector.TracingModel.Phase.Complete, e.startTime, e.thread) ;
213 jsFrameEvent.ordinal = e.ordinal; 213 jsFrameEvent.ordinal = e.ordinal;
214 jsFrameEvent.addArgs({ data: frame }); 214 jsFrameEvent.addArgs({ data: frame });
215 jsFrameEvent.setEndTime(endTime); 215 jsFrameEvent.setEndTime(endTime);
216 jsFramesStack.push(jsFrameEvent); 216 jsFramesStack.push(jsFrameEvent);
217 jsFrameEvents.push(jsFrameEvent); 217 jsFrameEvents.push(jsFrameEvent);
218 } 218 }
219 } 219 }
220 220
(...skipping 22 matching lines...) Expand all
243 WebInspector.TimelineJSProfileProcessor.CodeMap = function() 243 WebInspector.TimelineJSProfileProcessor.CodeMap = function()
244 { 244 {
245 /** @type {!Map<string, !WebInspector.TimelineJSProfileProcessor.CodeMap.Ban k>} */ 245 /** @type {!Map<string, !WebInspector.TimelineJSProfileProcessor.CodeMap.Ban k>} */
246 this._banks = new Map(); 246 this._banks = new Map();
247 } 247 }
248 248
249 /** 249 /**
250 * @constructor 250 * @constructor
251 * @param {number} address 251 * @param {number} address
252 * @param {number} size 252 * @param {number} size
253 * @param {!ConsoleAgent.CallFrame} callFrame 253 * @param {!RuntimeAgent.CallFrame} callFrame
254 */ 254 */
255 WebInspector.TimelineJSProfileProcessor.CodeMap.Entry = function(address, size, callFrame) 255 WebInspector.TimelineJSProfileProcessor.CodeMap.Entry = function(address, size, callFrame)
256 { 256 {
257 this.address = address; 257 this.address = address;
258 this.size = size; 258 this.size = size;
259 this.callFrame = callFrame; 259 this.callFrame = callFrame;
260 } 260 }
261 261
262 /** 262 /**
263 * @param {number} address 263 * @param {number} address
264 * @param {!WebInspector.TimelineJSProfileProcessor.CodeMap.Entry} entry 264 * @param {!WebInspector.TimelineJSProfileProcessor.CodeMap.Entry} entry
265 * @return {number} 265 * @return {number}
266 */ 266 */
267 WebInspector.TimelineJSProfileProcessor.CodeMap.comparator = function(address, e ntry) 267 WebInspector.TimelineJSProfileProcessor.CodeMap.comparator = function(address, e ntry)
268 { 268 {
269 return address - entry.address; 269 return address - entry.address;
270 } 270 }
271 271
272 WebInspector.TimelineJSProfileProcessor.CodeMap.prototype = { 272 WebInspector.TimelineJSProfileProcessor.CodeMap.prototype = {
273 /** 273 /**
274 * @param {string} addressHex 274 * @param {string} addressHex
275 * @param {number} size 275 * @param {number} size
276 * @param {!ConsoleAgent.CallFrame} callFrame 276 * @param {!RuntimeAgent.CallFrame} callFrame
277 */ 277 */
278 addEntry: function(addressHex, size, callFrame) 278 addEntry: function(addressHex, size, callFrame)
279 { 279 {
280 var entry = new WebInspector.TimelineJSProfileProcessor.CodeMap.Entry(th is._getAddress(addressHex), size, callFrame); 280 var entry = new WebInspector.TimelineJSProfileProcessor.CodeMap.Entry(th is._getAddress(addressHex), size, callFrame);
281 this._addEntry(addressHex, entry); 281 this._addEntry(addressHex, entry);
282 }, 282 },
283 283
284 /** 284 /**
285 * @param {string} oldAddressHex 285 * @param {string} oldAddressHex
286 * @param {string} newAddressHex 286 * @param {string} newAddressHex
287 * @param {number} size 287 * @param {number} size
288 */ 288 */
289 moveEntry: function(oldAddressHex, newAddressHex, size) 289 moveEntry: function(oldAddressHex, newAddressHex, size)
290 { 290 {
291 var entry = this._getBank(oldAddressHex).removeEntry(this._getAddress(ol dAddressHex)); 291 var entry = this._getBank(oldAddressHex).removeEntry(this._getAddress(ol dAddressHex));
292 if (!entry) { 292 if (!entry) {
293 console.error("Entry at address " + oldAddressHex + " not found"); 293 console.error("Entry at address " + oldAddressHex + " not found");
294 return; 294 return;
295 } 295 }
296 entry.address = this._getAddress(newAddressHex); 296 entry.address = this._getAddress(newAddressHex);
297 entry.size = size; 297 entry.size = size;
298 this._addEntry(newAddressHex, entry); 298 this._addEntry(newAddressHex, entry);
299 }, 299 },
300 300
301 /** 301 /**
302 * @param {string} addressHex 302 * @param {string} addressHex
303 * @return {?ConsoleAgent.CallFrame} 303 * @return {?RuntimeAgent.CallFrame}
304 */ 304 */
305 lookupEntry: function(addressHex) 305 lookupEntry: function(addressHex)
306 { 306 {
307 return this._getBank(addressHex).lookupEntry(this._getAddress(addressHex )); 307 return this._getBank(addressHex).lookupEntry(this._getAddress(addressHex ));
308 }, 308 },
309 309
310 /** 310 /**
311 * @param {string} addressHex 311 * @param {string} addressHex
312 * @param {!WebInspector.TimelineJSProfileProcessor.CodeMap.Entry} entry 312 * @param {!WebInspector.TimelineJSProfileProcessor.CodeMap.Entry} entry
313 */ 313 */
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 var index = this._entries.lowerBound(address, WebInspector.TimelineJSPro fileProcessor.CodeMap.comparator); 368 var index = this._entries.lowerBound(address, WebInspector.TimelineJSPro fileProcessor.CodeMap.comparator);
369 var entry = this._entries[index]; 369 var entry = this._entries[index];
370 if (!entry || entry.address !== address) 370 if (!entry || entry.address !== address)
371 return null; 371 return null;
372 this._entries.splice(index, 1); 372 this._entries.splice(index, 1);
373 return entry; 373 return entry;
374 }, 374 },
375 375
376 /** 376 /**
377 * @param {number} address 377 * @param {number} address
378 * @return {?ConsoleAgent.CallFrame} 378 * @return {?RuntimeAgent.CallFrame}
379 */ 379 */
380 lookupEntry: function(address) 380 lookupEntry: function(address)
381 { 381 {
382 var index = this._entries.upperBound(address, WebInspector.TimelineJSPro fileProcessor.CodeMap.comparator) - 1; 382 var index = this._entries.upperBound(address, WebInspector.TimelineJSPro fileProcessor.CodeMap.comparator) - 1;
383 var entry = this._entries[index]; 383 var entry = this._entries[index];
384 return entry && address < entry.address + entry.size ? entry.callFrame : null; 384 return entry && address < entry.address + entry.size ? entry.callFrame : null;
385 }, 385 },
386 386
387 /** 387 /**
388 * @param {!WebInspector.TimelineJSProfileProcessor.CodeMap.Entry} newEntry 388 * @param {!WebInspector.TimelineJSProfileProcessor.CodeMap.Entry} newEntry
(...skipping 10 matching lines...) Expand all
399 break; 399 break;
400 } 400 }
401 ++index; 401 ++index;
402 this._entries.splice(index, lastIndex - index, newEntry); 402 this._entries.splice(index, lastIndex - index, newEntry);
403 } 403 }
404 } 404 }
405 405
406 /** 406 /**
407 * @param {string} name 407 * @param {string} name
408 * @param {number} scriptId 408 * @param {number} scriptId
409 * @return {!ConsoleAgent.CallFrame} 409 * @return {!RuntimeAgent.CallFrame}
410 */ 410 */
411 WebInspector.TimelineJSProfileProcessor._buildCallFrame = function(name, scriptI d) 411 WebInspector.TimelineJSProfileProcessor._buildCallFrame = function(name, scriptI d)
412 { 412 {
413 /** 413 /**
414 * @param {string} functionName 414 * @param {string} functionName
415 * @param {string=} url 415 * @param {string=} url
416 * @param {string=} scriptId 416 * @param {string=} scriptId
417 * @param {number=} line 417 * @param {number=} line
418 * @param {number=} column 418 * @param {number=} column
419 * @param {boolean=} isNative 419 * @param {boolean=} isNative
420 * @return {!ConsoleAgent.CallFrame} 420 * @return {!RuntimeAgent.CallFrame}
421 */ 421 */
422 function createFrame(functionName, url, scriptId, line, column, isNative) 422 function createFrame(functionName, url, scriptId, line, column, isNative)
423 { 423 {
424 return /** @type {!ConsoleAgent.CallFrame} */ ({ 424 return /** @type {!RuntimeAgent.CallFrame} */ ({
425 "functionName": functionName, 425 "functionName": functionName,
426 "url": url || "", 426 "url": url || "",
427 "scriptId": scriptId || "0", 427 "scriptId": scriptId || "0",
428 "lineNumber": line || 0, 428 "lineNumber": line || 0,
429 "columnNumber": column || 0, 429 "columnNumber": column || 0,
430 "isNative": isNative || false 430 "isNative": isNative || false
431 }); 431 });
432 } 432 }
433 433
434 // Code states: 434 // Code states:
(...skipping 27 matching lines...) Expand all
462 /** 462 /**
463 * @param {!Array<!WebInspector.TracingModel.Event>} events 463 * @param {!Array<!WebInspector.TracingModel.Event>} events
464 * @return {!Array<!WebInspector.TracingModel.Event>} 464 * @return {!Array<!WebInspector.TracingModel.Event>}
465 */ 465 */
466 WebInspector.TimelineJSProfileProcessor.processRawV8Samples = function(events) 466 WebInspector.TimelineJSProfileProcessor.processRawV8Samples = function(events)
467 { 467 {
468 var missingAddesses = new Set(); 468 var missingAddesses = new Set();
469 469
470 /** 470 /**
471 * @param {string} address 471 * @param {string} address
472 * @return {?ConsoleAgent.CallFrame} 472 * @return {?RuntimeAgent.CallFrame}
473 */ 473 */
474 function convertRawFrame(address) 474 function convertRawFrame(address)
475 { 475 {
476 var entry = codeMap.lookupEntry(address); 476 var entry = codeMap.lookupEntry(address);
477 if (entry) 477 if (entry)
478 return entry.isNative ? null : entry; 478 return entry.isNative ? null : entry;
479 if (!missingAddesses.has(address)) { 479 if (!missingAddesses.has(address)) {
480 missingAddesses.add(address); 480 missingAddesses.add(address);
481 console.error("Address " + address + " has missing code entry"); 481 console.error("Address " + address + " has missing code entry");
482 } 482 }
(...skipping 28 matching lines...) Expand all
511 WebInspector.TracingModel.Phase.Instant, e.startTime, e.thread); 511 WebInspector.TracingModel.Phase.Instant, e.startTime, e.thread);
512 sampleEvent.ordinal = e.ordinal; 512 sampleEvent.ordinal = e.ordinal;
513 sampleEvent.args = {"data": {"stackTrace": stack }}; 513 sampleEvent.args = {"data": {"stackTrace": stack }};
514 samples.push(sampleEvent); 514 samples.push(sampleEvent);
515 break; 515 break;
516 } 516 }
517 } 517 }
518 518
519 return samples; 519 return samples;
520 } 520 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698