blob: dd0ac78489a79051b1ac84994653a4f8a9ee71cb [file] [log] [blame]
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {SelectionEvent} from './events.mjs';
import {DOM, V8CustomElement} from './helper.mjs';
import {delay, LazyTable} from './helper.mjs';
DOM.defineCustomElement(
'stats-panel', (templateText) => class StatsPanel extends V8CustomElement {
_timeline;
_transitions;
_selectedLogEntries;
constructor() {
super(templateText);
}
get stats() {
return this.$('#stats');
}
set timeline(timeline) {
this._timeline = timeline;
this.selectedLogEntries = timeline.all
}
set selectedLogEntries(entries) {
this._selectedLogEntries = entries;
this.update();
}
set transitions(value) {
this._transitions = value;
}
_filterUniqueTransitions(filter) {
// Returns a list of Maps whose parent is not in the list.
return this._selectedLogEntries.filter((map) => {
if (filter(map) === false) return false;
let parent = map.parent();
if (parent === undefined) return true;
return filter(parent) === false;
});
}
_update() {
this._updateGeneralStats();
this._updateNamedTransitionsStats();
}
_updateGeneralStats() {
console.assert(this._timeline !== undefined, 'Timeline not set yet!');
let pairs = [
['Transitions', 'primary', (e) => e.edge && e.edge.isTransition()],
['Fast to Slow', 'violet', (e) => e.edge && e.edge.isFastToSlow()],
['Slow to Fast', 'orange', (e) => e.edge && e.edge.isSlowToFast()],
['Initial Map', 'yellow', (e) => e.edge && e.edge.isInitial()],
[
'Replace Descriptors',
'red',
(e) => e.edge && e.edge.isReplaceDescriptors(),
],
[
'Copy as Prototype',
'red',
(e) => e.edge && e.edge.isCopyAsPrototype(),
],
[
'Optimize as Prototype',
null,
(e) => e.edge && e.edge.isOptimizeAsPrototype(),
],
['Deprecated', null, (e) => e.isDeprecated()],
['Bootstrapped', 'green', (e) => e.isBootstrapped()],
['Total', null, (e) => true],
];
let tbody = document.createElement('tbody');
let total = this._selectedLogEntries.length;
pairs.forEach(([name, color, filter]) => {
let row = DOM.tr();
if (color !== null) {
row.appendChild(DOM.td(DOM.div(['colorbox', color])));
} else {
row.appendChild(DOM.td(''));
}
row.classList.add('clickable');
row.onclick = (e) => {
// lazily compute the stats
let node = e.target.parentNode;
if (node.maps == undefined) {
node.maps = this._filterUniqueTransitions(filter);
}
this.dispatchEvent(new SelectionEvent(node.maps));
};
row.appendChild(DOM.td(name));
let count = this._count(filter);
row.appendChild(DOM.td(count));
let percent = Math.round((count / total) * 1000) / 10;
row.appendChild(DOM.td(percent.toFixed(1) + '%'));
tbody.appendChild(row);
});
this.$('#typeTable').replaceChild(tbody, this.$('#typeTable tbody'));
}
_count(filter) {
let count = 0;
for (const map of this._selectedLogEntries) {
if (filter(map)) count++;
}
return count;
}
_updateNamedTransitionsStats() {
let rowData = Array.from(this._transitions.entries());
rowData.sort((a, b) => b[1].length - a[1].length);
new LazyTable(this.$('#nameTable'), rowData, ([name, maps]) => {
let row = DOM.tr();
row.maps = maps;
row.classList.add('clickable');
row.addEventListener(
'click',
(e) => this.dispatchEvent(new SelectionEvent(
e.target.parentNode.maps.map((map) => map.to))));
row.appendChild(DOM.td(maps.length));
row.appendChild(DOM.td(name));
return row;
});
}
});