1 // Copyright 2013 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 var worker_scripts = [ 29 "../csvparser.js", 30 "../splaytree.js", 31 "../codemap.js", 32 "../consarray.js", 33 "../profile.js", 34 "../profile_view.js", 35 "../logreader.js", 36 "../tickprocessor.js", 37 "composer.js", 38 "gnuplot-4.6.3-emscripten.js" 39 ]; 40 41 42 function plotWorker() { 43 var worker = null; 44 45 var delegateList = { 46 "log" : log, 47 "error" : logError, 48 "displayplot" : displayplot, 49 "displayprof" : displayprof, 50 "range" : setRange, 51 "script" : scriptLoaded 52 } 53 54 function initialize() { 55 ui.freeze(); 56 worker = new Worker("worker.js"); 57 running = false; 58 59 worker.postMessage({ "call" : "load scripts", 60 "args" : worker_scripts }); 61 62 worker.addEventListener("message", function(event) { 63 var call = delegateList[event.data["call"]]; 64 call(event.data["args"]); 65 }); 66 } 67 68 function scriptLoaded() { 69 ui.thaw(); 70 } 71 72 // Public methods. 73 this.run = function(filename, 74 resx, resy, 75 distortion, 76 range_start, range_end) { 77 var args = { 78 'file' : filename, 79 'resx' : resx, 80 'resy' : resy, 81 'distortion' : distortion, 82 'range_start' : range_start, 83 'range_end' : range_end 84 } 85 worker.postMessage({ 'call' : 'run', 'args' : args }); 86 } 87 88 this.reset = function() { 89 if (worker) worker.terminate(); 90 initialize(); 91 } 92 } 93 94 95 function UIWrapper() { 96 var input_elements = ["range_start", 97 "range_end", 98 "distortion", 99 "start", 100 "file"]; 101 102 var other_elements = ["log", 103 "plot", 104 "prof", 105 "instructions", 106 "credits", 107 "toggledisplay"]; 108 109 for (var i in input_elements) { 110 var id = input_elements[i]; 111 this[id] = document.getElementById(id); 112 } 113 114 for (var i in other_elements) { 115 var id = other_elements[i]; 116 this[id] = document.getElementById(id); 117 } 118 119 this.freeze = function() { 120 this.plot.style.webkitFilter = "grayscale(1)"; 121 this.prof.style.color = "#bbb"; 122 for (var i in input_elements) { 123 this[input_elements[i]].disabled = true; 124 } 125 } 126 127 this.thaw = function() { 128 this.plot.style.webkitFilter = ""; 129 this.prof.style.color = "#000"; 130 for (var i in input_elements) { 131 this[input_elements[i]].disabled = false; 132 } 133 } 134 135 this.reset = function() { 136 this.thaw(); 137 this.log.value = ""; 138 this.range_start.value = "automatic"; 139 this.range_end.value = "automatic"; 140 this.toggle("plot"); 141 this.plot.src = ""; 142 this.prof.value = ""; 143 } 144 145 this.toggle = function(mode) { 146 if (mode) this.toggledisplay.next_mode = mode; 147 if (this.toggledisplay.next_mode == "plot") { 148 this.toggledisplay.next_mode = "prof"; 149 this.plot.style.display = "block"; 150 this.prof.style.display = "none"; 151 this.toggledisplay.innerHTML = "Show profile"; 152 } else { 153 this.toggledisplay.next_mode = "plot"; 154 this.plot.style.display = "none"; 155 this.prof.style.display = "block"; 156 this.toggledisplay.innerHTML = "Show plot"; 157 } 158 } 159 160 this.info = function(field) { 161 var down_arrow = "\u25bc"; 162 var right_arrow = "\u25b6"; 163 if (field && this[field].style.display != "none") field = null; // Toggle. 164 this.credits.style.display = "none"; 165 this.instructions.style.display = "none"; 166 if (!field) return; 167 this[field].style.display = "block"; 168 } 169 } 170 171 172 function log(text) { 173 ui.log.value += text; 174 ui.log.scrollTop = ui.log.scrollHeight; 175 } 176 177 178 function logError(text) { 179 if (ui.log.value.length > 0 && 180 ui.log.value[ui.log.value.length-1] != "\n") { 181 ui.log.value += "\n"; 182 } 183 ui.log.value += "ERROR: " + text + "\n"; 184 ui.log.scrollTop = ui.log.scrollHeight; 185 error_logged = true; 186 } 187 188 189 function displayplot(args) { 190 if (error_logged) { 191 log("Plot failed.\n\n"); 192 } else { 193 log("Displaying plot. Total time: " + 194 (Date.now() - timer) / 1000 + "ms.\n\n"); 195 var blob = new Blob([new Uint8Array(args.contents).buffer], 196 { "type" : "image\/svg+xml" }); 197 window.URL = window.URL || window.webkitURL; 198 ui.plot.src = window.URL.createObjectURL(blob); 199 } 200 201 ui.thaw(); 202 ui.toggle("plot"); 203 } 204 205 206 function displayprof(args) { 207 if (error_logged) return; 208 ui.prof.value = args; 209 this.prof.style.color = ""; 210 ui.toggle("prof"); 211 } 212 213 214 function start(event) { 215 error_logged = false; 216 ui.freeze(); 217 218 try { 219 var file = getSelectedFile(); 220 var distortion = getDistortion(); 221 var range = getRange(); 222 } catch (e) { 223 logError(e.message); 224 display(); 225 return; 226 } 227 228 timer = Date.now(); 229 worker.run(file, kResX, kResY, distortion, range[0], range[1]); 230 } 231 232 233 function getSelectedFile() { 234 var file = ui.file.files[0]; 235 if (!file) throw Error("No valid file selected."); 236 if (!file.type.toString().match(/text/)) { 237 throw Error("'" + escape(file.name) + "' is not a text file."); 238 } 239 return file; 240 } 241 242 243 function getDistortion() { 244 var input_distortion = 245 parseInt(ui.distortion.value, 10); 246 if (isNaN(input_distortion)) { 247 input_distortion = ui.distortion.value = 4500; 248 } 249 return input_distortion / 1000000; 250 } 251 252 253 function getRange() { 254 var input_start = 255 parseInt(ui.range_start.value, 10); 256 if (isNaN(input_start)) input_start = undefined; 257 var input_end = 258 parseInt(ui.range_end.value, 10); 259 if (isNaN(input_end)) input_end = undefined; 260 return [input_start, input_end]; 261 } 262 263 264 function setRange(args) { 265 ui.range_start.value = args.start.toFixed(1); 266 ui.range_end.value = args.end.toFixed(1); 267 } 268 269 270 function onload() { 271 kResX = 1200; 272 kResY = 600; 273 error_logged = false; 274 ui = new UIWrapper(); 275 ui.reset(); 276 ui.info(null); 277 worker = new plotWorker(); 278 worker.reset(); 279 } 280 281 282 var kResX; 283 var kResY; 284 var error_logged; 285 var ui; 286 var worker; 287 var timer; 288