Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE
This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.
FPIIM-449
Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/tools/ic-explorer.html b/tools/ic-explorer.html
new file mode 100644
index 0000000..43b486a
--- /dev/null
+++ b/tools/ic-explorer.html
@@ -0,0 +1,338 @@
+<html>
+ <head>
+<style>
+ .entry-details {
+ }
+ .entry-details TD {
+ }
+ .details {
+ width: 2em;
+ border: 1px black dotted;
+ }
+ .count {
+ text-align: right;
+ width: 5em;
+ font-family: monospace;
+ }
+ .percentage {
+ text-align: right;
+ width: 5em;
+ font-family: monospace;
+ }
+ .key {
+ padding-left: 1em;
+ }
+ .drilldown-group-title {
+ font-weight: bold;
+ padding: 0.5em 0 0.2em 0;
+ }
+</style>
+ <script>
+"use strict"
+var entries = [];
+
+class Entry {
+ constructor(id, line) {
+ this.id = id;
+ this.line = line;
+ var parts = line.split(" ");
+ if (parts.length < 6) return
+ this.isValid = false;
+ if (parts[0][0] !== "[") return;
+ if (parts[1] === "patching") return;
+ this.type = parts[0].substr(1);
+ this.category = "Other";
+ if (this.type.indexOf("Store") !== -1) {
+ this.category = "Store";
+ } else if (this.type.indexOf("Load") !== -1) {
+ this.category = "Load";
+ }
+ if (this.type.length == 0) return;
+ if (this.type.indexOf('BinaryOpIC(') === 0) {
+ this.type = "BinaryOpIC";
+ var split = parts[0].split('(');
+ this.state = "(" + split[1] + " => " + parts[2];
+ var offset = this.parsePositionAndFile(parts, 6);
+ if (offset == -1) return
+ if (this.file === undefined) return
+ this.file = this.file.slice(0,-1);
+ } else {
+ var offset = this.parsePositionAndFile(parts, 2);
+ if (offset == -1) return
+ this.state = parts[++offset];
+ if (this.type !== "CompareIC") {
+ // if there is no address we have a smi key
+ var address = parts[++offset];
+ if (address !== undefined && address.indexOf("0x") === 0) {
+ this.key = parts.slice(++offset).join(" ");
+ } else {
+ this.key = address;
+ }
+ }
+ }
+ this.filePosition = this.file + " " + this.position;
+ if (this.key) {
+ var isStringKey = false
+ if (this.key.indexOf("<String[") === 0) {
+ isStringKey = true;
+ this.key = "\"" + this.key.slice(this.key.indexOf(']')+3);
+ } else if (this.key.indexOf("<") === 0) {
+ this.key = this.key.slice(1);
+ }
+ if (this.key.endsWith(">]")) {
+ this.key = this.key.slice(0, -2);
+ } else if (this.key.endsWith("]")) {
+ this.key = this.key.slice(0, -1);
+ }
+ if (isStringKey) {
+ this.key = this.key + "\"";
+ }
+ }
+ this.isValid = true;
+ }
+
+ parsePositionAndFile(parts, start) {
+ // find the position of 'at' in the parts array.
+ var offset = start;
+ for (var i = start+1; i<parts.length; i++) {
+ offset++;
+ if (parts[i] == 'at') break;
+ }
+ if (parts[offset] !== 'at') return -1;
+ this.position = parts.slice(start, offset).join(' ');
+ offset += 1;
+ this.isNative = parts[offset] == "native"
+ offset += this.isNative ? 1 : 0;
+ this.file = parts[offset];
+ return offset;
+ }
+}
+
+function loadFile() {
+ var files = document.getElementById("uploadInput").files;
+
+ var file = files[0];
+ var reader = new FileReader();
+
+ reader.onload = function(evt) {
+ entries = [];
+ var end = this.result.length;
+ var current = 0;
+ var next = 0;
+ var line;
+ var i = 0;
+ var entry;
+ while (current < end) {
+ next = this.result.indexOf("\n", current);
+ if (next === -1) break;
+ i++;
+
+ line = this.result.substring(current, next);
+ current = next+1;
+ entry = new Entry(i, line);
+ if (entry.isValid) entries.push(entry);
+ }
+
+ document.getElementById("count").innerHTML = i;
+ updateTable();
+ }
+ reader.readAsText(file);
+ initGroupKeySelect();
+}
+
+
+
+var properties = ['type', 'category', 'file', 'filePosition', 'state' , 'key', 'isNative']
+
+class Group {
+ constructor(property, key, entry) {
+ this.property = property;
+ this.key = key;
+ this.count = 1;
+ this.entries = [entry];
+ this.percentage = undefined;
+ this.groups = undefined;
+ }
+
+ add(entry) {
+ this.count ++;
+ this.entries.push(entry)
+ }
+
+ createSubGroups() {
+ this.groups = {};
+ for (var i=0; i<properties.length; i++) {
+ var subProperty = properties[i];
+ if (this.property == subProperty) continue;
+ this.groups[subProperty] = groupBy(this.entries, subProperty);
+ }
+ }
+}
+
+function groupBy(entries, property) {
+ var accumulator = {};
+ accumulator.__proto__ = null;
+ var length = entries.length;
+ for (var i = 0; i < length; i++) {
+ var entry = entries[i];
+ var key = entry[property];
+ if (accumulator[key] == undefined) {
+ accumulator[key] = new Group(property, key, entry)
+ } else {
+ var group = accumulator[key];
+ if (group.entries == undefined) console.log([group, entry]);
+ group.add(entry)
+ }
+ }
+ var result = []
+ for (var key in accumulator) {
+ var group = accumulator[key];
+ group.percentage = Math.round(group.count / length * 100 * 100) / 100;
+ result.push(group);
+ }
+ result.sort((a,b) => { return b.count - a.count });
+ return result;
+}
+
+
+
+
+function updateTable() {
+ var select = document.getElementById("group-key");
+ var key = select.options[select.selectedIndex].text;
+ console.log(key);
+ var tableBody = document.getElementById("table-body");
+ removeAllChildren(tableBody);
+ var groups = groupBy(entries, key, true);
+ display(groups, tableBody);
+}
+
+function selecedOption(node) {
+ return node.options[node.selectedIndex]
+}
+
+function removeAllChildren(node) {
+ while (node.firstChild) {
+ node.removeChild(node.firstChild);
+ }
+}
+
+function display(entries, parent) {
+ var fragment = document.createDocumentFragment();
+
+ function td(tr, content, className) {
+ var td = document.createElement("td");
+ td.innerHTML = content;
+ td.className = className
+ tr.appendChild(td);
+ return td
+ }
+ var max = Math.min(1000, entries.length)
+ for (var i = 0; i<max; i++) {
+ var entry = entries[i];
+ var tr = document.createElement("tr");
+ tr.entry = entry;
+ td(tr, '<span onclick="toggleDetails(this)">details</a>', 'details');
+ td(tr, entry.percentage +"%", 'percentage');
+ td(tr, entry.count, 'count');
+ td(tr, entry.key, 'key');
+ fragment.appendChild(tr);
+ }
+ var omitted = entries.length - max;
+ if (omitted > 0) {
+ var tr = document.createElement("tr");
+ var td = td(tr, 'Omitted ' + omitted + " entries.");
+ td.colSpan = 4;
+ fragment.appendChild(tr);
+ }
+ parent.appendChild(fragment);
+}
+
+function displayDrilldown(entry, previousSibling) {
+ var tr = document.createElement('tr');
+ tr.className = "entry-details";
+ tr.style.display = "none";
+ // indent by one td.
+ tr.appendChild(document.createElement("td"));
+ var td = document.createElement("td");
+ td.colSpan = 3;
+ for (var key in entry.groups) {
+ td.appendChild(displayDrilldownGroup(entry, key));
+ }
+ tr.appendChild(td);
+ // Append the new TR after previousSibling.
+ previousSibling.parentNode.insertBefore(tr, previousSibling.nextSibling)
+}
+
+function displayDrilldownGroup(entry, key) {
+ var max = 20;
+ var group = entry.groups[key];
+ var div = document.createElement("div")
+ div.className = 'drilldown-group-title'
+ div.innerHTML = key + ' [top ' + max + ']';
+ var table = document.createElement("table");
+ display(group.slice(0, max), table, false)
+ div.appendChild(table);
+ return div;
+}
+
+function toggleDetails(node) {
+ var tr = node.parentNode.parentNode;
+ var entry = tr.entry;
+
+ // Create subgroup in-place if the don't exist yet.
+ if (entry.groups === undefined) {
+ entry.createSubGroups();
+ displayDrilldown(entry, tr);
+ }
+ var details = tr.nextSibling;
+ var display = details.style.display;
+ if (display != "none") {
+ display = "none";
+ }else {
+ display = "table-row"
+ };
+ details.style.display = display;
+}
+
+function initGroupKeySelect() {
+ var select = document.getElementById("group-key");
+ for (var i in properties) {
+ var option = document.createElement("option");
+ option.text = properties[i];
+ select.add(option);
+ }
+}
+
+ </script>
+ </head>
+ <body>
+ <h1>
+ <span style="color: #00FF00">I</span>
+ <span style="color: #FF00FF">C</span>
+ <span style="color: #00FFFF">E</span>
+ </h1>
+ Your IC-Explorer.
+ <h2>Usage</h2>
+ Run your script with <code>--trace_ic</code> and upload on this page:<br/>
+ <code>/path/to/d8 --trace_ic your_script.js > trace.txt</code>
+ <h2>Data</h2>
+ <form name="fileForm">
+ <p>
+ <input id="uploadInput" type="file" name="files" onchange="loadFile();" >
+ trace entries: <span id="count">0</span>
+ </p>
+ </form>
+ <h2>Result</h2>
+ <p>
+ Group-Key:
+ <select id="group-key" onchange="updateTable()"></select>
+ </p>
+ <p>
+ <table id="table" width="100%">
+ <tbody id="table-body">
+ </tbody>
+ </table>
+ </p>
+ </body>
+</html>