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 3 // found in the LICENSE file. 4 5 6 WebInspector.TimelineJSProfileProcessor = { }; 7 8 /** 9 * @param {!WebInspector.TimelineModelImpl} timelineModel 10 * @param {!ProfilerAgent.CPUProfile} jsProfile 11 */ 12 WebInspector.TimelineJSProfileProcessor.mergeJSProfileIntoTimeline = function(timelineModel, jsProfile) 13 { 14 if (!jsProfile.samples) 15 return; 16 var jsProfileModel = new WebInspector.CPUProfileDataModel(jsProfile); 17 var idleNode = jsProfileModel.idleNode; 18 var programNode = jsProfileModel.programNode; 19 var gcNode = jsProfileModel.gcNode; 20 21 /** 22 * @param {!WebInspector.TimelineModel.Record} record 23 */ 24 function processRecord(record) 25 { 26 if (record.type() !== WebInspector.TimelineModel.RecordType.FunctionCall && 27 record.type() !== WebInspector.TimelineModel.RecordType.EvaluateScript) 28 return; 29 var recordStartTime = record.startTime(); 30 var recordEndTime = record.endTime(); 31 var originalChildren = record.children().splice(0); 32 var childIndex = 0; 33 34 /** 35 * @param {number} depth 36 * @param {!ProfilerAgent.CPUProfileNode} node 37 * @param {number} startTime 38 */ 39 function onOpenFrame(depth, node, startTime) 40 { 41 if (node === idleNode || node === programNode || node === gcNode) 42 return; 43 var event = { 44 type: "JSFrame", 45 data: node, 46 startTime: startTime 47 }; 48 putOriginalChildrenUpToTime(startTime); 49 record = new WebInspector.TimelineModel.RecordImpl(timelineModel, event, record); 50 } 51 52 /** 53 * @param {number} depth 54 * @param {!ProfilerAgent.CPUProfileNode} node 55 * @param {number} startTime 56 * @param {number} totalTime 57 * @param {number} selfTime 58 */ 59 function onCloseFrame(depth, node, startTime, totalTime, selfTime) 60 { 61 if (node === idleNode || node === programNode || node === gcNode) 62 return; 63 record.setEndTime(Math.min(startTime + totalTime, recordEndTime)); 64 record._selfTime = record.endTime() - record.startTime(); 65 putOriginalChildrenUpToTime(record.endTime()); 66 var deoptReason = node.deoptReason; 67 if (deoptReason && deoptReason !== "no reason") 68 record.addWarning(deoptReason); 69 record = record.parent; 70 } 71 72 /** 73 * @param {number} endTime 74 */ 75 function putOriginalChildrenUpToTime(endTime) 76 { 77 for (; childIndex < originalChildren.length; ++childIndex) { 78 var child = originalChildren[childIndex]; 79 var midTime = (child.startTime() + child.endTime()) / 2; 80 if (midTime >= endTime) 81 break; 82 child.parent = record; 83 record.children().push(child); 84 } 85 } 86 87 jsProfileModel.forEachFrame(onOpenFrame, onCloseFrame, recordStartTime, recordEndTime); 88 putOriginalChildrenUpToTime(recordEndTime); 89 } 90 91 timelineModel.forAllRecords(processRecord); 92 } 93 94 /** 95 * @param {!WebInspector.TracingTimelineModel} timelineModel 96 * @param {!ProfilerAgent.CPUProfile} jsProfile 97 * @return {!Array.<!WebInspector.TracingModel.Event>} 98 */ 99 WebInspector.TimelineJSProfileProcessor.generateTracingEventsFromCpuProfile = function(timelineModel, jsProfile) 100 { 101 if (!jsProfile.samples) 102 return []; 103 var jsProfileModel = new WebInspector.CPUProfileDataModel(jsProfile); 104 var idleNode = jsProfileModel.idleNode; 105 var programNode = jsProfileModel.programNode; 106 var gcNode = jsProfileModel.gcNode; 107 var samples = jsProfileModel.samples; 108 var timestamps = jsProfileModel.timestamps; 109 var jsEvents = []; 110 var mainThread = timelineModel.mainThreadEvents()[0].thread; 111 for (var i = 0; i < samples.length; ++i) { 112 var node = jsProfileModel.nodeByIndex(i); 113 if (node === programNode || node === gcNode || node === idleNode) 114 continue; 115 var stackTrace = node._stackTraceArray; 116 if (!stackTrace) { 117 stackTrace = /** @type {!ConsoleAgent.StackTrace} */ (new Array(node.depth + 1)); 118 node._stackTraceArray = stackTrace; 119 for (var j = 0; node.parent; node = node.parent) 120 stackTrace[j++] = /** @type {!ConsoleAgent.CallFrame} */ (node); 121 } 122 var jsEvent = new WebInspector.TracingModel.Event(WebInspector.TracingModel.DevToolsMetadataEventCategory, WebInspector.TracingTimelineModel.RecordType.JSSample, 123 WebInspector.TracingModel.Phase.Instant, timestamps[i], mainThread); 124 jsEvent.stackTrace = stackTrace; 125 jsEvents.push(jsEvent); 126 } 127 return jsEvents; 128 } 129