blob: 8ac0881eb6fb216f5f20d0385207767575febc58 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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;