176 lines
5.8 KiB
JavaScript
176 lines
5.8 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/. */
|
||
"use strict";
|
||
|
||
const { LocalizationHelper } = require("devtools/shared/l10n");
|
||
const STRINGS_URI = "devtools/client/locales/jit-optimizations.properties";
|
||
const L10N = new LocalizationHelper(STRINGS_URI);
|
||
|
||
const {PluralForm} = require("devtools/shared/plural-form");
|
||
const { DOM: dom, PropTypes, createClass, createFactory } = require("devtools/client/shared/vendor/react");
|
||
const Frame = createFactory(require("devtools/client/shared/components/frame"));
|
||
const PROPNAME_MAX_LENGTH = 4;
|
||
// If TREE_ROW_HEIGHT changes, be sure to change `var(--jit-tree-row-height)`
|
||
// in `devtools/client/themes/jit-optimizations.css`
|
||
const TREE_ROW_HEIGHT = 14;
|
||
|
||
const OPTIMIZATION_ITEM_TYPES = ["site", "attempts", "types", "attempt", "type",
|
||
"observedtype"];
|
||
|
||
/* eslint-disable no-unused-vars */
|
||
/**
|
||
* TODO - Re-enable this eslint rule. The JIT tool is a work in progress, and isn't fully
|
||
* integrated as of yet.
|
||
*/
|
||
const {
|
||
JITOptimizations, hasSuccessfulOutcome, isSuccessfulOutcome
|
||
} = require("devtools/client/performance/modules/logic/jit");
|
||
const OPTIMIZATION_FAILURE = L10N.getStr("jit.optimizationFailure");
|
||
const JIT_SAMPLES = L10N.getStr("jit.samples");
|
||
const JIT_TYPES = L10N.getStr("jit.types");
|
||
const JIT_ATTEMPTS = L10N.getStr("jit.attempts");
|
||
/* eslint-enable no-unused-vars */
|
||
|
||
const JITOptimizationsItem = createClass({
|
||
displayName: "JITOptimizationsItem",
|
||
|
||
propTypes: {
|
||
onViewSourceInDebugger: PropTypes.func.isRequired,
|
||
frameData: PropTypes.object.isRequired,
|
||
type: PropTypes.oneOf(OPTIMIZATION_ITEM_TYPES).isRequired,
|
||
},
|
||
|
||
_renderSite({ item: site, onViewSourceInDebugger, frameData }) {
|
||
let attempts = site.data.attempts;
|
||
let lastStrategy = attempts[attempts.length - 1].strategy;
|
||
let propString = "";
|
||
let propertyName = site.data.propertyName;
|
||
|
||
// Display property name if it exists
|
||
if (propertyName) {
|
||
if (propertyName.length > PROPNAME_MAX_LENGTH) {
|
||
propString = ` (.${propertyName.substr(0, PROPNAME_MAX_LENGTH)}…)`;
|
||
} else {
|
||
propString = ` (.${propertyName})`;
|
||
}
|
||
}
|
||
|
||
let sampleString = PluralForm.get(site.samples, JIT_SAMPLES)
|
||
.replace("#1", site.samples);
|
||
let text = dom.span(
|
||
{ className: "optimization-site-title" },
|
||
`${lastStrategy}${propString} – (${sampleString})`
|
||
);
|
||
let frame = Frame({
|
||
onClick: () => onViewSourceInDebugger(frameData.url, site.data.line),
|
||
frame: {
|
||
source: frameData.url,
|
||
line: +site.data.line,
|
||
column: site.data.column,
|
||
}
|
||
});
|
||
let children = [text, frame];
|
||
|
||
if (!hasSuccessfulOutcome(site)) {
|
||
children.unshift(dom.span({ className: "opt-icon warning" }));
|
||
}
|
||
|
||
return dom.span({ className: "optimization-site" }, ...children);
|
||
},
|
||
|
||
_renderAttempts({ item: attempts }) {
|
||
return dom.span({ className: "optimization-attempts" },
|
||
`${JIT_ATTEMPTS} (${attempts.length})`
|
||
);
|
||
},
|
||
|
||
_renderTypes({ item: types }) {
|
||
return dom.span({ className: "optimization-types" },
|
||
`${JIT_TYPES} (${types.length})`
|
||
);
|
||
},
|
||
|
||
_renderAttempt({ item: attempt }) {
|
||
let success = isSuccessfulOutcome(attempt.outcome);
|
||
let { strategy, outcome } = attempt;
|
||
return dom.span({ className: "optimization-attempt" },
|
||
dom.span({ className: "optimization-strategy" }, strategy),
|
||
" → ",
|
||
dom.span({ className: `optimization-outcome ${success ? "success" : "failure"}` },
|
||
outcome)
|
||
);
|
||
},
|
||
|
||
_renderType({ item: type }) {
|
||
return dom.span({ className: "optimization-ion-type" },
|
||
`${type.site}:${type.mirType}`);
|
||
},
|
||
|
||
_renderObservedType({ onViewSourceInDebugger, item: type }) {
|
||
let children = [
|
||
dom.span({ className: "optimization-observed-type-keyed" },
|
||
`${type.keyedBy}${type.name ? ` → ${type.name}` : ""}`)
|
||
];
|
||
|
||
// If we have a line and location, make a link to the debugger
|
||
if (type.location && type.line) {
|
||
children.push(
|
||
Frame({
|
||
onClick: () => onViewSourceInDebugger(type.location, type.line),
|
||
frame: {
|
||
source: type.location,
|
||
line: type.line,
|
||
column: type.column,
|
||
}
|
||
})
|
||
);
|
||
// Otherwise if we just have a location, it's probably just a memory location.
|
||
} else if (type.location) {
|
||
children.push(`@${type.location}`);
|
||
}
|
||
|
||
return dom.span({ className: "optimization-observed-type" }, ...children);
|
||
},
|
||
|
||
render() {
|
||
/* eslint-disable no-unused-vars */
|
||
/**
|
||
* TODO - Re-enable this eslint rule. The JIT tool is a work in progress, and these
|
||
* undefined variables may represent intended functionality.
|
||
*/
|
||
let {
|
||
depth,
|
||
arrow,
|
||
type,
|
||
// TODO - The following are currently unused.
|
||
item,
|
||
focused,
|
||
frameData,
|
||
onViewSourceInDebugger,
|
||
} = this.props;
|
||
/* eslint-enable no-unused-vars */
|
||
|
||
let content;
|
||
switch (type) {
|
||
case "site": content = this._renderSite(this.props); break;
|
||
case "attempts": content = this._renderAttempts(this.props); break;
|
||
case "types": content = this._renderTypes(this.props); break;
|
||
case "attempt": content = this._renderAttempt(this.props); break;
|
||
case "type": content = this._renderType(this.props); break;
|
||
case "observedtype": content = this._renderObservedType(this.props); break;
|
||
}
|
||
|
||
return dom.div(
|
||
{
|
||
className: `optimization-tree-item optimization-tree-item-${type}`,
|
||
style: { marginInlineStart: depth * TREE_ROW_HEIGHT }
|
||
},
|
||
arrow,
|
||
content
|
||
);
|
||
},
|
||
});
|
||
|
||
module.exports = JITOptimizationsItem;
|