v8/tools/profviz/profviz.js
2013-07-02 15:34:28 +00:00

288 lines
7.4 KiB
JavaScript

// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
var worker_scripts = [
"../csvparser.js",
"../splaytree.js",
"../codemap.js",
"../consarray.js",
"../profile.js",
"../profile_view.js",
"../logreader.js",
"../tickprocessor.js",
"composer.js",
"gnuplot-4.6.3-emscripten.js"
];
function plotWorker() {
var worker = null;
var delegateList = {
"log" : log,
"error" : logError,
"displayplot" : displayplot,
"displayprof" : displayprof,
"range" : setRange,
"script" : scriptLoaded
}
function initialize() {
ui.freeze();
worker = new Worker("worker.js");
running = false;
worker.postMessage({ "call" : "load scripts",
"args" : worker_scripts });
worker.addEventListener("message", function(event) {
var call = delegateList[event.data["call"]];
call(event.data["args"]);
});
}
function scriptLoaded() {
ui.thaw();
}
// Public methods.
this.run = function(filename,
resx, resy,
distortion,
range_start, range_end) {
var args = {
'file' : filename,
'resx' : resx,
'resy' : resy,
'distortion' : distortion,
'range_start' : range_start,
'range_end' : range_end
}
worker.postMessage({ 'call' : 'run', 'args' : args });
}
this.reset = function() {
if (worker) worker.terminate();
initialize();
}
}
function UIWrapper() {
var input_elements = ["range_start",
"range_end",
"distortion",
"start",
"file"];
var other_elements = ["log",
"plot",
"prof",
"instructions",
"credits",
"toggledisplay"];
for (var i in input_elements) {
var id = input_elements[i];
this[id] = document.getElementById(id);
}
for (var i in other_elements) {
var id = other_elements[i];
this[id] = document.getElementById(id);
}
this.freeze = function() {
this.plot.style.webkitFilter = "grayscale(1)";
this.prof.style.color = "#bbb";
for (var i in input_elements) {
this[input_elements[i]].disabled = true;
}
}
this.thaw = function() {
this.plot.style.webkitFilter = "";
this.prof.style.color = "#000";
for (var i in input_elements) {
this[input_elements[i]].disabled = false;
}
}
this.reset = function() {
this.thaw();
this.log.value = "";
this.range_start.value = "automatic";
this.range_end.value = "automatic";
this.toggle("plot");
this.plot.src = "";
this.prof.value = "";
}
this.toggle = function(mode) {
if (mode) this.toggledisplay.next_mode = mode;
if (this.toggledisplay.next_mode == "plot") {
this.toggledisplay.next_mode = "prof";
this.plot.style.display = "block";
this.prof.style.display = "none";
this.toggledisplay.innerHTML = "Show profile";
} else {
this.toggledisplay.next_mode = "plot";
this.plot.style.display = "none";
this.prof.style.display = "block";
this.toggledisplay.innerHTML = "Show plot";
}
}
this.info = function(field) {
var down_arrow = "\u25bc";
var right_arrow = "\u25b6";
if (field && this[field].style.display != "none") field = null; // Toggle.
this.credits.style.display = "none";
this.instructions.style.display = "none";
if (!field) return;
this[field].style.display = "block";
}
}
function log(text) {
ui.log.value += text;
ui.log.scrollTop = ui.log.scrollHeight;
}
function logError(text) {
if (ui.log.value.length > 0 &&
ui.log.value[ui.log.value.length-1] != "\n") {
ui.log.value += "\n";
}
ui.log.value += "ERROR: " + text + "\n";
ui.log.scrollTop = ui.log.scrollHeight;
error_logged = true;
}
function displayplot(args) {
if (error_logged) {
log("Plot failed.\n\n");
} else {
log("Displaying plot. Total time: " +
(Date.now() - timer) / 1000 + "ms.\n\n");
var blob = new Blob([new Uint8Array(args.contents).buffer],
{ "type" : "image\/svg+xml" });
window.URL = window.URL || window.webkitURL;
ui.plot.src = window.URL.createObjectURL(blob);
}
ui.thaw();
ui.toggle("plot");
}
function displayprof(args) {
if (error_logged) return;
ui.prof.value = args;
this.prof.style.color = "";
ui.toggle("prof");
}
function start(event) {
error_logged = false;
ui.freeze();
try {
var file = getSelectedFile();
var distortion = getDistortion();
var range = getRange();
} catch (e) {
logError(e.message);
display();
return;
}
timer = Date.now();
worker.run(file, kResX, kResY, distortion, range[0], range[1]);
}
function getSelectedFile() {
var file = ui.file.files[0];
if (!file) throw Error("No valid file selected.");
if (!file.type.toString().match(/text/)) {
throw Error("'" + escape(file.name) + "' is not a text file.");
}
return file;
}
function getDistortion() {
var input_distortion =
parseInt(ui.distortion.value, 10);
if (isNaN(input_distortion)) {
input_distortion = ui.distortion.value = 4500;
}
return input_distortion / 1000000;
}
function getRange() {
var input_start =
parseInt(ui.range_start.value, 10);
if (isNaN(input_start)) input_start = undefined;
var input_end =
parseInt(ui.range_end.value, 10);
if (isNaN(input_end)) input_end = undefined;
return [input_start, input_end];
}
function setRange(args) {
ui.range_start.value = args.start.toFixed(1);
ui.range_end.value = args.end.toFixed(1);
}
function onload() {
kResX = 1200;
kResY = 600;
error_logged = false;
ui = new UIWrapper();
ui.reset();
ui.info(null);
worker = new plotWorker();
worker.reset();
}
var kResX;
var kResY;
var error_logged;
var ui;
var worker;
var timer;