blob: 175adbc2ef23a08813f1de4edcd9689c64c049d1 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
WebInspector.TimelineJSProfileProcessor = { };
/**
* @param {!WebInspector.TimelineModelImpl} timelineModel
* @param {!ProfilerAgent.CPUProfile} jsProfile
*/
WebInspector.TimelineJSProfileProcessor.mergeJSProfileIntoTimeline = function(timelineModel, jsProfile)
{
if (!jsProfile.samples)
return;
var jsProfileModel = new WebInspector.CPUProfileDataModel(jsProfile);
var idleNode = jsProfileModel.idleNode;
var programNode = jsProfileModel.programNode;
var gcNode = jsProfileModel.gcNode;
/**
* @param {!WebInspector.TimelineModel.Record} record
*/
function processRecord(record)
{
if (record.type() !== WebInspector.TimelineModel.RecordType.FunctionCall &&
record.type() !== WebInspector.TimelineModel.RecordType.EvaluateScript)
return;
var recordStartTime = record.startTime();
var recordEndTime = record.endTime();
var originalChildren = record.children().splice(0);
var childIndex = 0;
/**
* @param {number} depth
* @param {!ProfilerAgent.CPUProfileNode} node
* @param {number} startTime
*/
function onOpenFrame(depth, node, startTime)
{
if (node === idleNode || node === programNode || node === gcNode)
return;
var event = {
type: "JSFrame",
data: node,
startTime: startTime
};
putOriginalChildrenUpToTime(startTime);
record = new WebInspector.TimelineModel.RecordImpl(timelineModel, event, record);
}
/**
* @param {number} depth
* @param {!ProfilerAgent.CPUProfileNode} node
* @param {number} startTime
* @param {number} totalTime
* @param {number} selfTime
*/
function onCloseFrame(depth, node, startTime, totalTime, selfTime)
{
if (node === idleNode || node === programNode || node === gcNode)
return;
record.setEndTime(Math.min(startTime + totalTime, recordEndTime));
record._selfTime = record.endTime() - record.startTime();
putOriginalChildrenUpToTime(record.endTime());
var deoptReason = node.deoptReason;
if (deoptReason && deoptReason !== "no reason")
record.addWarning(deoptReason);
record = record.parent;
}
/**
* @param {number} endTime
*/
function putOriginalChildrenUpToTime(endTime)
{
for (; childIndex < originalChildren.length; ++childIndex) {
var child = originalChildren[childIndex];
var midTime = (child.startTime() + child.endTime()) / 2;
if (midTime >= endTime)
break;
child.parent = record;
record.children().push(child);
}
}
jsProfileModel.forEachFrame(onOpenFrame, onCloseFrame, recordStartTime, recordEndTime);
putOriginalChildrenUpToTime(recordEndTime);
}
timelineModel.forAllRecords(processRecord);
}
/**
* @param {!WebInspector.TracingTimelineModel} timelineModel
* @param {!ProfilerAgent.CPUProfile} jsProfile
* @return {!Array.<!WebInspector.TracingModel.Event>}
*/
WebInspector.TimelineJSProfileProcessor.generateTracingEventsFromCpuProfile = function(timelineModel, jsProfile)
{
if (!jsProfile.samples)
return [];
var jsProfileModel = new WebInspector.CPUProfileDataModel(jsProfile);
var idleNode = jsProfileModel.idleNode;
var programNode = jsProfileModel.programNode;
var gcNode = jsProfileModel.gcNode;
var samples = jsProfileModel.samples;
var timestamps = jsProfileModel.timestamps;
var jsEvents = [];
var mainThread = timelineModel.mainThreadEvents()[0].thread;
for (var i = 0; i < samples.length; ++i) {
var node = jsProfileModel.nodeByIndex(i);
if (node === programNode || node === gcNode || node === idleNode)
continue;
var stackTrace = node._stackTraceArray;
if (!stackTrace) {
stackTrace = /** @type {!ConsoleAgent.StackTrace} */ (new Array(node.depth + 1));
node._stackTraceArray = stackTrace;
for (var j = 0; node.parent; node = node.parent)
stackTrace[j++] = /** @type {!ConsoleAgent.CallFrame} */ (node);
}
var jsEvent = new WebInspector.TracingModel.Event(WebInspector.TracingModel.DevToolsMetadataEventCategory, WebInspector.TracingTimelineModel.RecordType.JSSample,
WebInspector.TracingModel.Phase.Instant, timestamps[i], mainThread);
jsEvent.stackTrace = stackTrace;
jsEvents.push(jsEvent);
}
return jsEvents;
}