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 28var 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 "../arguments.js", 37 "../tickprocessor.js", 38 "composer.js", 39 "gnuplot-4.6.3-emscripten.js" 40]; 41 42 43function plotWorker() { 44 var worker = null; 45 46 function initialize() { 47 ui.freeze(); 48 worker = new Worker("worker.js"); 49 running = false; 50 51 worker.postMessage({ "call" : "load scripts", 52 "args" : worker_scripts }); 53 54 worker.addEventListener("message", function(event) { 55 var call = delegateList[event.data["call"]]; 56 call(event.data["args"]); 57 }); 58 } 59 60 function scriptLoaded() { 61 ui.thaw(); 62 } 63 64 // Public methods. 65 this.run = function(filename, 66 resx, resy, 67 distortion, 68 range_start, range_end) { 69 var args = { 70 'file' : filename, 71 'resx' : resx, 72 'resy' : resy, 73 'distortion' : distortion, 74 'range_start' : range_start, 75 'range_end' : range_end 76 } 77 worker.postMessage({ 'call' : 'run', 'args' : args }); 78 } 79 80 this.reset = function() { 81 if (worker) worker.terminate(); 82 initialize(); 83 } 84 85 var delegateList = { 86 "log" : log, 87 "error" : logError, 88 "displayplot" : displayplot, 89 "displayprof" : displayprof, 90 "range" : setRange, 91 "script" : scriptLoaded, 92 "reset" : this.reset 93 } 94} 95 96 97function UIWrapper() { 98 var input_elements = ["range_start", 99 "range_end", 100 "distortion", 101 "start", 102 "file"]; 103 104 var other_elements = ["log", 105 "plot", 106 "prof", 107 "instructions", 108 "credits", 109 "toggledisplay"]; 110 111 for (var i in input_elements) { 112 var id = input_elements[i]; 113 this[id] = document.getElementById(id); 114 } 115 116 for (var i in other_elements) { 117 var id = other_elements[i]; 118 this[id] = document.getElementById(id); 119 } 120 121 this.freeze = function() { 122 this.plot.style.webkitFilter = "grayscale(1)"; 123 this.prof.style.color = "#bbb"; 124 for (var i in input_elements) { 125 this[input_elements[i]].disabled = true; 126 } 127 } 128 129 this.thaw = function() { 130 this.plot.style.webkitFilter = ""; 131 this.prof.style.color = "#000"; 132 for (var i in input_elements) { 133 this[input_elements[i]].disabled = false; 134 } 135 } 136 137 this.reset = function() { 138 this.thaw(); 139 this.log.value = ""; 140 this.range_start.value = "automatic"; 141 this.range_end.value = "automatic"; 142 this.toggle("plot"); 143 this.plot.src = ""; 144 this.prof.value = ""; 145 } 146 147 this.toggle = function(mode) { 148 if (mode) this.toggledisplay.next_mode = mode; 149 if (this.toggledisplay.next_mode == "plot") { 150 this.toggledisplay.next_mode = "prof"; 151 this.plot.style.display = "block"; 152 this.prof.style.display = "none"; 153 this.toggledisplay.innerHTML = "Show profile"; 154 } else { 155 this.toggledisplay.next_mode = "plot"; 156 this.plot.style.display = "none"; 157 this.prof.style.display = "block"; 158 this.toggledisplay.innerHTML = "Show plot"; 159 } 160 } 161 162 this.info = function(field) { 163 var down_arrow = "\u25bc"; 164 var right_arrow = "\u25b6"; 165 if (field && this[field].style.display != "none") field = null; // Toggle. 166 this.credits.style.display = "none"; 167 this.instructions.style.display = "none"; 168 if (!field) return; 169 this[field].style.display = "block"; 170 } 171} 172 173 174function log(text) { 175 ui.log.value += text; 176 ui.log.scrollTop = ui.log.scrollHeight; 177} 178 179 180function logError(text) { 181 if (ui.log.value.length > 0 && 182 ui.log.value[ui.log.value.length-1] != "\n") { 183 ui.log.value += "\n"; 184 } 185 ui.log.value += "ERROR: " + text + "\n"; 186 ui.log.scrollTop = ui.log.scrollHeight; 187 error_logged = true; 188} 189 190 191function displayplot(args) { 192 if (error_logged) { 193 log("Plot failed.\n\n"); 194 } else { 195 log("Displaying plot. Total time: " + 196 (Date.now() - timer) / 1000 + "ms.\n\n"); 197 var blob = new Blob([new Uint8Array(args.contents).buffer], 198 { "type" : "image\/svg+xml" }); 199 window.URL = window.URL || window.webkitURL; 200 ui.plot.src = window.URL.createObjectURL(blob); 201 } 202 203 ui.thaw(); 204 ui.toggle("plot"); 205} 206 207 208function displayprof(args) { 209 if (error_logged) return; 210 ui.prof.value = args; 211 this.prof.style.color = ""; 212 ui.toggle("prof"); 213} 214 215 216function start(event) { 217 error_logged = false; 218 ui.freeze(); 219 220 try { 221 var file = getSelectedFile(); 222 var distortion = getDistortion(); 223 var range = getRange(); 224 } catch (e) { 225 logError(e.message); 226 display(); 227 return; 228 } 229 230 timer = Date.now(); 231 worker.run(file, kResX, kResY, distortion, range[0], range[1]); 232} 233 234 235function getSelectedFile() { 236 var file = ui.file.files[0]; 237 if (!file) throw Error("No valid file selected."); 238 return file; 239} 240 241 242function getDistortion() { 243 var input_distortion = 244 parseInt(ui.distortion.value, 10); 245 if (isNaN(input_distortion)) { 246 input_distortion = ui.distortion.value = 4500; 247 } 248 return input_distortion / 1000000; 249} 250 251 252function getRange() { 253 var input_start = 254 parseInt(ui.range_start.value, 10); 255 if (isNaN(input_start)) input_start = undefined; 256 var input_end = 257 parseInt(ui.range_end.value, 10); 258 if (isNaN(input_end)) input_end = undefined; 259 return [input_start, input_end]; 260} 261 262 263function setRange(args) { 264 ui.range_start.value = args.start.toFixed(1); 265 ui.range_end.value = args.end.toFixed(1); 266} 267 268 269function onload() { 270 kResX = 1200; 271 kResY = 600; 272 error_logged = false; 273 ui = new UIWrapper(); 274 ui.reset(); 275 ui.info(null); 276 worker = new plotWorker(); 277 worker.reset(); 278} 279 280 281var kResX; 282var kResY; 283var error_logged; 284var ui; 285var worker; 286var timer; 287