blob: 42bbc2039618a3e7aead36733f0ec68b5ebefff2 [file] [log] [blame]
Ben Murdoch097c5b22016-05-18 11:27:45 +01001<html>
Ben Murdochc5610432016-08-08 18:44:38 +01002<!--
3Copyright 2016 the V8 project authors. All rights reserved. Use of this source
4code is governed by a BSD-style license that can be found in the LICENSE file.
5-->
Ben Murdoch097c5b22016-05-18 11:27:45 +01006
Ben Murdochc5610432016-08-08 18:44:38 +01007<head>
8 <style>
9 .entry-details {}
10
11 .entry-details TD {}
12
13 .details {
14 width: 2em;
15 border: 1px black dotted;
Ben Murdoch097c5b22016-05-18 11:27:45 +010016 }
Ben Murdochc5610432016-08-08 18:44:38 +010017
18 .count {
19 text-align: right;
20 width: 5em;
21 font-family: monospace;
22 }
23
24 .percentage {
25 text-align: right;
26 width: 5em;
27 font-family: monospace;
28 }
29
30 .key {
31 padding-left: 1em;
32 }
33
34 .drilldown-group-title {
35 font-weight: bold;
36 padding: 0.5em 0 0.2em 0;
37 }
38 </style>
39 <script>
40 "use strict"
41 var entries = [];
42
43 class Entry {
44 constructor(id, line) {
45 this.id = id;
46 this.line = line;
47 var parts = line.split(" ");
48 if (parts.length < 6) return
49 this.isValid = false;
50 if (parts[0][0] !== "[") return;
51 if (parts[1] === "patching") return;
52 this.type = parts[0].substr(1);
53 this.category = "Other";
Ben Murdoch61f157c2016-09-16 13:49:30 +010054 this.map = undefined;
Ben Murdochc5610432016-08-08 18:44:38 +010055 if (this.type.indexOf("Store") !== -1) {
56 this.category = "Store";
57 } else if (this.type.indexOf("Load") !== -1) {
58 this.category = "Load";
59 }
60 if (this.type.length == 0) return;
61 if (this.type.indexOf('BinaryOpIC(') === 0) {
62 this.type = "BinaryOpIC";
63 var split = parts[0].split('(');
64 this.state = "(" + split[1] + " => " + parts[2];
65 var offset = this.parsePositionAndFile(parts, 6);
66 if (offset == -1) return
67 if (this.file === undefined) return
68 this.file = this.file.slice(0, -1);
Ben Murdoch097c5b22016-05-18 11:27:45 +010069 } else {
Ben Murdochc5610432016-08-08 18:44:38 +010070 var offset = this.parsePositionAndFile(parts, 2);
71 if (offset == -1) return
72 this.state = parts[++offset];
Ben Murdoch61f157c2016-09-16 13:49:30 +010073 this.map = parts[offset + 1];
74 if (this.map !== undefined && this.map.startsWith("map=")) {
75 this.map = this.map.substring(4);
76 offset++;
77 } else {
78 this.map = undefined;
79 }
Ben Murdochc5610432016-08-08 18:44:38 +010080 if (this.type !== "CompareIC") {
81 // if there is no address we have a smi key
82 var address = parts[++offset];
83 if (address !== undefined && address.indexOf("0x") === 0) {
84 this.key = parts.slice(++offset).join(" ");
85 } else {
86 this.key = address;
87 }
88 }
89 }
90 this.filePosition = this.file + " " + this.position;
91 if (this.key) {
92 var isStringKey = false
93 if (this.key.indexOf("<String[") === 0) {
94 isStringKey = true;
95 this.key = "\"" + this.key.slice(this.key.indexOf(']') + 3);
96 } else if (this.key.indexOf("<") === 0) {
97 this.key = this.key.slice(1);
98 }
99 if (this.key.endsWith(">]")) {
100 this.key = this.key.slice(0, -2);
101 } else if (this.key.endsWith("]")) {
102 this.key = this.key.slice(0, -1);
103 }
104 if (isStringKey) {
105 this.key = this.key + "\"";
106 }
107 }
108 this.isValid = true;
109 }
110
111 parsePositionAndFile(parts, start) {
112 // find the position of 'at' in the parts array.
113 var offset = start;
114 for (var i = start + 1; i < parts.length; i++) {
115 offset++;
116 if (parts[i] == 'at') break;
117 }
118 if (parts[offset] !== 'at') return -1;
119 this.position = parts.slice(start, offset).join(' ');
120 offset += 1;
121 this.isNative = parts[offset] == "native"
122 offset += this.isNative ? 1 : 0;
123 this.file = parts[offset];
124 return offset;
125 }
126 }
127
128 function loadFile() {
129 var files = document.getElementById("uploadInput").files;
130
131 var file = files[0];
132 var reader = new FileReader();
133
134 reader.onload = function(evt) {
135 entries = [];
136 var end = this.result.length;
137 var current = 0;
138 var next = 0;
139 var line;
140 var i = 0;
141 var entry;
142 while (current < end) {
143 next = this.result.indexOf("\n", current);
144 if (next === -1) break;
145 i++;
Ben Murdochc5610432016-08-08 18:44:38 +0100146 line = this.result.substring(current, next);
147 current = next + 1;
148 entry = new Entry(i, line);
149 if (entry.isValid) entries.push(entry);
150 }
151
152 document.getElementById("count").innerHTML = i;
153 updateTable();
154 }
155 reader.readAsText(file);
156 initGroupKeySelect();
157 }
158
159
160
161 var properties = ['type', 'category', 'file', 'filePosition', 'state',
Ben Murdoch61f157c2016-09-16 13:49:30 +0100162 'key', 'isNative', 'map'
Ben Murdochc5610432016-08-08 18:44:38 +0100163 ]
164
165 class Group {
166 constructor(property, key, entry) {
167 this.property = property;
168 this.key = key;
169 this.count = 1;
170 this.entries = [entry];
171 this.percentage = undefined;
172 this.groups = undefined;
173 }
174
175 add(entry) {
176 this.count++;
177 this.entries.push(entry)
178 }
179
180 createSubGroups() {
181 this.groups = {};
182 for (var i = 0; i < properties.length; i++) {
183 var subProperty = properties[i];
184 if (this.property == subProperty) continue;
185 this.groups[subProperty] = groupBy(this.entries, subProperty);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100186 }
187 }
188 }
Ben Murdochc5610432016-08-08 18:44:38 +0100189
190 function groupBy(entries, property) {
191 var accumulator = {};
192 accumulator.__proto__ = null;
193 var length = entries.length;
194 for (var i = 0; i < length; i++) {
195 var entry = entries[i];
196 var key = entry[property];
197 if (accumulator[key] == undefined) {
198 accumulator[key] = new Group(property, key, entry)
199 } else {
200 var group = accumulator[key];
201 if (group.entries == undefined) console.log([group, entry]);
202 group.add(entry)
203 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100204 }
Ben Murdochc5610432016-08-08 18:44:38 +0100205 var result = []
206 for (var key in accumulator) {
207 var group = accumulator[key];
208 group.percentage = Math.round(group.count / length * 100 * 100) / 100;
209 result.push(group);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100210 }
Ben Murdochc5610432016-08-08 18:44:38 +0100211 result.sort((a, b) => {
212 return b.count - a.count
213 });
214 return result;
215 }
216
217
218
Ben Murdoch61f157c2016-09-16 13:49:30 +0100219 function escapeHtml(unsafe) {
220 if (!unsafe) return "";
221 return unsafe.toString()
222 .replace(/&/g, "&amp;")
223 .replace(/</g, "&lt;")
224 .replace(/>/g, "&gt;")
225 .replace(/"/g, "&quot;")
226 .replace(/'/g, "&#039;");
227 }
Ben Murdochc5610432016-08-08 18:44:38 +0100228
229 function updateTable() {
230 var select = document.getElementById("group-key");
231 var key = select.options[select.selectedIndex].text;
232 console.log(key);
233 var tableBody = document.getElementById("table-body");
234 removeAllChildren(tableBody);
235 var groups = groupBy(entries, key, true);
236 display(groups, tableBody);
237 }
238
239 function selecedOption(node) {
240 return node.options[node.selectedIndex]
241 }
242
243 function removeAllChildren(node) {
244 while (node.firstChild) {
245 node.removeChild(node.firstChild);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100246 }
247 }
Ben Murdochc5610432016-08-08 18:44:38 +0100248
249 function display(entries, parent) {
250 var fragment = document.createDocumentFragment();
251
252 function td(tr, content, className) {
253 var td = document.createElement("td");
254 td.innerHTML = content;
255 td.className = className
256 tr.appendChild(td);
257 return td
258 }
259 var max = Math.min(1000, entries.length)
260 for (var i = 0; i < max; i++) {
261 var entry = entries[i];
262 var tr = document.createElement("tr");
263 tr.entry = entry;
264 td(tr, '<span onclick="toggleDetails(this)">details</a>', 'details');
265 td(tr, entry.percentage + "%", 'percentage');
266 td(tr, entry.count, 'count');
Ben Murdoch61f157c2016-09-16 13:49:30 +0100267 td(tr, escapeHtml(entry.key), 'key');
Ben Murdochc5610432016-08-08 18:44:38 +0100268 fragment.appendChild(tr);
269 }
270 var omitted = entries.length - max;
271 if (omitted > 0) {
272 var tr = document.createElement("tr");
273 var td = td(tr, 'Omitted ' + omitted + " entries.");
274 td.colSpan = 4;
275 fragment.appendChild(tr);
276 }
277 parent.appendChild(fragment);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100278 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100279
Ben Murdochc5610432016-08-08 18:44:38 +0100280 function displayDrilldown(entry, previousSibling) {
281 var tr = document.createElement('tr');
282 tr.className = "entry-details";
283 tr.style.display = "none";
284 // indent by one td.
285 tr.appendChild(document.createElement("td"));
286 var td = document.createElement("td");
287 td.colSpan = 3;
288 for (var key in entry.groups) {
289 td.appendChild(displayDrilldownGroup(entry, key));
290 }
291 tr.appendChild(td);
292 // Append the new TR after previousSibling.
293 previousSibling.parentNode.insertBefore(tr, previousSibling.nextSibling)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100294 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100295
Ben Murdochc5610432016-08-08 18:44:38 +0100296 function displayDrilldownGroup(entry, key) {
297 var max = 20;
298 var group = entry.groups[key];
299 var div = document.createElement("div")
300 div.className = 'drilldown-group-title'
Ben Murdoch61f157c2016-09-16 13:49:30 +0100301 div.innerHTML = key + ' [top ' + max + ' out of ' + group.length + ']';
Ben Murdochc5610432016-08-08 18:44:38 +0100302 var table = document.createElement("table");
303 display(group.slice(0, max), table, false)
304 div.appendChild(table);
305 return div;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100306 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100307
Ben Murdochc5610432016-08-08 18:44:38 +0100308 function toggleDetails(node) {
309 var tr = node.parentNode.parentNode;
310 var entry = tr.entry;
311
312 // Create subgroup in-place if the don't exist yet.
313 if (entry.groups === undefined) {
314 entry.createSubGroups();
315 displayDrilldown(entry, tr);
316 }
317 var details = tr.nextSibling;
318 var display = details.style.display;
319 if (display != "none") {
320 display = "none";
321 } else {
322 display = "table-row"
323 };
324 details.style.display = display;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100325 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100326
Ben Murdochc5610432016-08-08 18:44:38 +0100327 function initGroupKeySelect() {
328 var select = document.getElementById("group-key");
329 for (var i in properties) {
330 var option = document.createElement("option");
331 option.text = properties[i];
332 select.add(option);
333 }
334 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100335 </script>
Ben Murdochc5610432016-08-08 18:44:38 +0100336</head>
337
338<body>
339 <h1>
Ben Murdoch097c5b22016-05-18 11:27:45 +0100340 <span style="color: #00FF00">I</span>
341 <span style="color: #FF00FF">C</span>
342 <span style="color: #00FFFF">E</span>
Ben Murdochc5610432016-08-08 18:44:38 +0100343 </h1> Your IC-Explorer.
344 <h2>Usage</h2> Run your script with <code>--trace_ic</code> and upload on this page:<br/>
345 <code>/path/to/d8 --trace_ic your_script.js > trace.txt</code>
346 <h2>Data</h2>
347 <form name="fileForm">
Ben Murdoch097c5b22016-05-18 11:27:45 +0100348 <p>
Ben Murdochc5610432016-08-08 18:44:38 +0100349 <input id="uploadInput" type="file" name="files" onchange="loadFile();"> trace
350 entries: <span id="count">0</span>
351 </p>
352 </form>
353 <h2>Result</h2>
354 <p>
Ben Murdoch097c5b22016-05-18 11:27:45 +0100355 Group-Key:
356 <select id="group-key" onchange="updateTable()"></select>
Ben Murdochc5610432016-08-08 18:44:38 +0100357 </p>
358 <p>
359 <table id="table" width="100%">
360 <tbody id="table-body">
361 </tbody>
362 </table>
363 </p>
364</body>
365
Ben Murdoch097c5b22016-05-18 11:27:45 +0100366</html>