tenfourfox/devtools/client/performance/views/details-js-call-tree.js
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

166 lines
5.0 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* import-globals-from ../performance-controller.js */
/* import-globals-from ../performance-view.js */
"use strict";
/**
* CallTree view containing profiler call tree, controlled by DetailsView.
*/
var JsCallTreeView = Heritage.extend(DetailsSubview, {
rerenderPrefs: [
"invert-call-tree",
"show-platform-data",
"flatten-tree-recursion",
],
rangeChangeDebounceTime: 75, // ms
/**
* Sets up the view with event binding.
*/
initialize: function () {
DetailsSubview.initialize.call(this);
this._onLink = this._onLink.bind(this);
this._onFocus = this._onFocus.bind(this);
this.container = $("#js-calltree-view .call-tree-cells-container");
OptimizationsListView.initialize();
},
/**
* Unbinds events.
*/
destroy: function () {
OptimizationsListView.destroy();
this.container = null;
this.threadNode = null;
DetailsSubview.destroy.call(this);
},
/**
* Method for handling all the set up for rendering a new call tree.
*
* @param object interval [optional]
* The { startTime, endTime }, in milliseconds.
*/
render: function (interval={}) {
let recording = PerformanceController.getCurrentRecording();
let profile = recording.getProfile();
let optimizations = recording.getConfiguration().withJITOptimizations;
let options = {
contentOnly: !PerformanceController.getOption("show-platform-data"),
invertTree: PerformanceController.getOption("invert-call-tree"),
flattenRecursion: PerformanceController.getOption("flatten-tree-recursion"),
showOptimizationHint: optimizations
};
let threadNode = this.threadNode = this._prepareCallTree(profile, interval, options);
this._populateCallTree(threadNode, options);
if (optimizations) {
this.showOptimizations();
} else {
this.hideOptimizations();
}
OptimizationsListView.reset();
this.emit(EVENTS.JS_CALL_TREE_RENDERED);
},
showOptimizations: function () {
$("#jit-optimizations-view").classList.remove("hidden");
},
hideOptimizations: function () {
$("#jit-optimizations-view").classList.add("hidden");
},
_onFocus: function (_, treeItem) {
if (PerformanceController.getCurrentRecording().getConfiguration().withJITOptimizations) {
OptimizationsListView.setCurrentFrame(this.threadNode, treeItem.frame);
OptimizationsListView.render();
}
this.emit("focus", treeItem);
},
/**
* Fired on the "link" event for the call tree in this container.
*/
_onLink: function (_, treeItem) {
let { url, line } = treeItem.frame.getInfo();
gToolbox.viewSourceInDebugger(url, line).then(success => {
if (success) {
this.emit(EVENTS.SOURCE_SHOWN_IN_JS_DEBUGGER);
} else {
this.emit(EVENTS.SOURCE_NOT_FOUND_IN_JS_DEBUGGER);
}
});
},
/**
* Called when the recording is stopped and prepares data to
* populate the call tree.
*/
_prepareCallTree: function (profile, { startTime, endTime }, options) {
let thread = profile.threads[0];
let { contentOnly, invertTree, flattenRecursion } = options;
let threadNode = new ThreadNode(thread, { startTime, endTime, contentOnly, invertTree, flattenRecursion });
// Real profiles from nsProfiler (i.e. not synthesized from allocation
// logs) always have a (root) node. Go down one level in the uninverted
// view to avoid displaying both the synthesized root node and the (root)
// node from the profiler.
if (!invertTree) {
threadNode.calls = threadNode.calls[0].calls;
}
return threadNode;
},
/**
* Renders the call tree.
*/
_populateCallTree: function (frameNode, options={}) {
// If we have an empty profile (no samples), then don't invert the tree, as
// it would hide the root node and a completely blank call tree space can be
// mis-interpreted as an error.
let inverted = options.invertTree && frameNode.samples > 0;
let root = new CallView({
frame: frameNode,
inverted: inverted,
// The synthesized root node is hidden in inverted call trees.
hidden: inverted,
// Call trees should only auto-expand when not inverted. Passing undefined
// will default to the CALL_TREE_AUTO_EXPAND depth.
autoExpandDepth: inverted ? 0 : undefined,
showOptimizationHint: options.showOptimizationHint
});
// Bind events.
root.on("link", this._onLink);
root.on("focus", this._onFocus);
// Clear out other call trees.
this.container.innerHTML = "";
root.attachTo(this.container);
// When platform data isn't shown, hide the cateogry labels, since they're
// only available for C++ frames. Pass *false* to make them invisible.
root.toggleCategories(!options.contentOnly);
// Return the CallView for tests
return root;
},
toString: () => "[object JsCallTreeView]"
});
EventEmitter.decorate(JsCallTreeView);