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