diff options
Diffstat (limited to 'devtools/client/performance/components/jit-optimizations-item.js')
-rw-r--r-- | devtools/client/performance/components/jit-optimizations-item.js | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/devtools/client/performance/components/jit-optimizations-item.js b/devtools/client/performance/components/jit-optimizations-item.js new file mode 100644 index 000000000..e5c77ef02 --- /dev/null +++ b/devtools/client/performance/components/jit-optimizations-item.js @@ -0,0 +1,175 @@ +/* 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; |