Commit 94bce1dc authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[tools] Convert JS-tools to ES6 modules

This changes all tools to use ES6 modules and proper imports.

Step 1: Add converted .mjs files (*this CL*)
Step 2: Update node-ci build to use new .mjs files
Step 3: Remove outdated .js files

Bug: v8:10667, v8:10933
Change-Id: I3e92e66f896d8a9cacaf6d421f8d2c86fb3bc444
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2431045
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran  <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70163}
parent 630fbf67
......@@ -15,15 +15,15 @@ group("v8_mjsunit") {
"../../tools/clusterfuzz/v8_mock.js",
"../../tools/clusterfuzz/v8_mock_archs.js",
"../../tools/clusterfuzz/v8_mock_webassembly.js",
"../../tools/codemap.js",
"../../tools/consarray.js",
"../../tools/csvparser.js",
"../../tools/logreader.js",
"../../tools/arguments.js",
"../../tools/profile.js",
"../../tools/profile_view.js",
"../../tools/splaytree.js",
"../../tools/tickprocessor.js",
"../../tools/dumpcpp.js",
"../../tools/codemap.mjs",
"../../tools/consarray.mjs",
"../../tools/csvparser.mjs",
"../../tools/logreader.mjs",
"../../tools/arguments.mjs",
"../../tools/profile.mjs",
"../../tools/profile_view.mjs",
"../../tools/splaytree.mjs",
"../../tools/tickprocessor.mjs",
"../../tools/dumpcpp.mjs",
]
}
......@@ -25,9 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Load Splay tree and CodeMap implementations from <project root>/tools.
// Files: tools/splaytree.js tools/codemap.js
import { CodeMap } from "../../../tools/codemap.mjs";
function newCodeEntry(size, name) {
return new CodeMap.CodeEntry(size, name);
......
......@@ -25,9 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Load ConsArray implementation from <project root>/tools.
// Files: tools/consarray.js
import { ConsArray } from "../../../tools/consarray.mjs";
var arr1 = new ConsArray();
assertTrue(arr1.atEnd());
......
......@@ -25,8 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Load CSV parser implementation from <project root>/tools.
// Files: tools/csvparser.js
import { CsvParser } from "../../../tools/csvparser.mjs";
var parser = new CsvParser();
......
......@@ -2,12 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Load implementations from <project root>/tools.
// Files: tools/splaytree.js tools/codemap.js tools/csvparser.js
// Files: tools/consarray.js tools/profile.js tools/profile_view.js
// Files: tools/logreader.js tools/arguments.js tools/tickprocessor.js
// Files: tools/dumpcpp.js
// Env: TEST_FILE_NAME
import {
CppProcessor, UnixCppEntriesProvider
} from "../../../tools/dumpcpp.mjs" ;
(function testProcessSharedLibrary() {
var oldLoadSymbols = UnixCppEntriesProvider.prototype.loadSymbols;
......
......@@ -25,9 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Load source code files from <project root>/tools.
// Files: tools/splaytree.js tools/codemap.js tools/consarray.js tools/profile.js
import { Profile } from "../../../tools/profile.mjs";
function stackToString(stack) {
return stack.join(' -> ');
......
......@@ -25,9 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Load source code files from <project root>/tools.
// Files: tools/codemap.js tools/consarray.js tools/profile.js
// Files: tools/profile_view.js
import { ProfileView } from "../../../tools/profile_view.mjs";
function createNode(name, time, opt_parent) {
......
......@@ -25,8 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Load the Splay tree implementation from <project root>/tools.
// Files: tools/splaytree.js
import { SplayTree } from "../../../tools/splaytree.mjs";
(function testIsEmpty() {
......
......@@ -25,10 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Load implementations from <project root>/tools.
// Files: tools/splaytree.js tools/codemap.js tools/csvparser.js
// Files: tools/consarray.js tools/profile.js tools/profile_view.js
// Files: tools/logreader.js tools/arguments.js tools/tickprocessor.js
// Resources: test/mjsunit/tools/tickprocessor-test-func-info.log
// Resources: test/mjsunit/tools/tickprocessor-test.default
// Resources: test/mjsunit/tools/tickprocessor-test.func-info
......@@ -39,6 +35,11 @@
// Resources: test/mjsunit/tools/tickprocessor-test.separate-ic
// Env: TEST_FILE_NAME
import {
TickProcessor, ArgumentsProcessor, UnixCppEntriesProvider,
MacCppEntriesProvider, WindowsCppEntriesProvider, readFile
} from "../../../tools/tickprocessor.mjs";
(function testArgumentsProcessor() {
var p_default = new ArgumentsProcessor([]);
......
This diff is collapsed.
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
export class BaseArgumentsProcessor {
constructor(args) {
this.args_ = args;
this.result_ = this.getDefaultResults();
console.assert(this.result_ !== undefined)
console.assert(this.result_.logFileName !== undefined);
this.argsDispatch_ = this.getArgsDispatch();
console.assert(this.argsDispatch_ !== undefined);
}
getDefaultResults() {
throw "Implement in getDefaultResults in subclass";
}
getArgsDispatch() {
throw "Implement getArgsDispatch in subclass";
}
result() { return this.result_ }
printUsageAndExit() {
print('Cmdline args: [options] [log-file-name]\n' +
'Default log file name is "' +
this.result_.logFileName + '".\n');
print('Options:');
for (var arg in this.argsDispatch_) {
var synonyms = [arg];
var dispatch = this.argsDispatch_[arg];
for (var synArg in this.argsDispatch_) {
if (arg !== synArg && dispatch === this.argsDispatch_[synArg]) {
synonyms.push(synArg);
delete this.argsDispatch_[synArg];
}
}
print(' ' + synonyms.join(', ').padEnd(20) + " " + dispatch[2]);
}
quit(2);
}
parse() {
while (this.args_.length) {
var arg = this.args_.shift();
if (arg.charAt(0) != '-') {
this.result_.logFileName = arg;
continue;
}
var userValue = null;
var eqPos = arg.indexOf('=');
if (eqPos != -1) {
userValue = arg.substr(eqPos + 1);
arg = arg.substr(0, eqPos);
}
if (arg in this.argsDispatch_) {
var dispatch = this.argsDispatch_[arg];
var property = dispatch[0];
var defaultValue = dispatch[1];
if (typeof defaultValue == "function") {
userValue = defaultValue(userValue);
} else if (userValue == null) {
userValue = defaultValue;
}
this.result_[property] = userValue;
} else {
return false;
}
}
return true;
}
}
export function parseBool(str) {
if (str == "true" || str == "1") return true;
return false;
}
// Copyright 2009 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.
import { SplayTree } from "./splaytree.mjs";
/**
* Constructs a mapper that maps addresses into code entries.
*
* @constructor
*/
export function CodeMap() {
/**
* Dynamic code entries. Used for JIT compiled code.
*/
this.dynamics_ = new SplayTree();
/**
* Name generator for entries having duplicate names.
*/
this.dynamicsNameGen_ = new CodeMap.NameGenerator();
/**
* Static code entries. Used for statically compiled code.
*/
this.statics_ = new SplayTree();
/**
* Libraries entries. Used for the whole static code libraries.
*/
this.libraries_ = new SplayTree();
/**
* Map of memory pages occupied with static code.
*/
this.pages_ = [];
};
/**
* The number of alignment bits in a page address.
*/
CodeMap.PAGE_ALIGNMENT = 12;
/**
* Page size in bytes.
*/
CodeMap.PAGE_SIZE =
1 << CodeMap.PAGE_ALIGNMENT;
/**
* Adds a dynamic (i.e. moveable and discardable) code entry.
*
* @param {number} start The starting address.
* @param {CodeMap.CodeEntry} codeEntry Code entry object.
*/
CodeMap.prototype.addCode = function(start, codeEntry) {
this.deleteAllCoveredNodes_(this.dynamics_, start, start + codeEntry.size);
this.dynamics_.insert(start, codeEntry);
};
/**
* Moves a dynamic code entry. Throws an exception if there is no dynamic
* code entry with the specified starting address.
*
* @param {number} from The starting address of the entry being moved.
* @param {number} to The destination address.
*/
CodeMap.prototype.moveCode = function(from, to) {
var removedNode = this.dynamics_.remove(from);
this.deleteAllCoveredNodes_(this.dynamics_, to, to + removedNode.value.size);
this.dynamics_.insert(to, removedNode.value);
};
/**
* Discards a dynamic code entry. Throws an exception if there is no dynamic
* code entry with the specified starting address.
*
* @param {number} start The starting address of the entry being deleted.
*/
CodeMap.prototype.deleteCode = function(start) {
var removedNode = this.dynamics_.remove(start);
};
/**
* Adds a library entry.
*
* @param {number} start The starting address.
* @param {CodeMap.CodeEntry} codeEntry Code entry object.
*/
CodeMap.prototype.addLibrary = function(
start, codeEntry) {
this.markPages_(start, start + codeEntry.size);
this.libraries_.insert(start, codeEntry);
};
/**
* Adds a static code entry.
*
* @param {number} start The starting address.
* @param {CodeMap.CodeEntry} codeEntry Code entry object.
*/
CodeMap.prototype.addStaticCode = function(
start, codeEntry) {
this.statics_.insert(start, codeEntry);
};
/**
* @private
*/
CodeMap.prototype.markPages_ = function(start, end) {
for (var addr = start; addr <= end;
addr += CodeMap.PAGE_SIZE) {
this.pages_[(addr / CodeMap.PAGE_SIZE)|0] = 1;
}
};
/**
* @private
*/
CodeMap.prototype.deleteAllCoveredNodes_ = function(tree, start, end) {
var to_delete = [];
var addr = end - 1;
while (addr >= start) {
var node = tree.findGreatestLessThan(addr);
if (!node) break;
var start2 = node.key, end2 = start2 + node.value.size;
if (start2 < end && start < end2) to_delete.push(start2);
addr = start2 - 1;
}
for (var i = 0, l = to_delete.length; i < l; ++i) tree.remove(to_delete[i]);
};
/**
* @private
*/
CodeMap.prototype.isAddressBelongsTo_ = function(addr, node) {
return addr >= node.key && addr < (node.key + node.value.size);
};
/**
* @private
*/
CodeMap.prototype.findInTree_ = function(tree, addr) {
var node = tree.findGreatestLessThan(addr);
return node && this.isAddressBelongsTo_(addr, node) ? node : null;
};
/**
* Finds a code entry that contains the specified address. Both static and
* dynamic code entries are considered. Returns the code entry and the offset
* within the entry.
*
* @param {number} addr Address.
*/
CodeMap.prototype.findAddress = function(addr) {
var pageAddr = (addr / CodeMap.PAGE_SIZE)|0;
if (pageAddr in this.pages_) {
// Static code entries can contain "holes" of unnamed code.
// In this case, the whole library is assigned to this address.
var result = this.findInTree_(this.statics_, addr);
if (!result) {
result = this.findInTree_(this.libraries_, addr);
if (!result) return null;
}
return { entry : result.value, offset : addr - result.key };
}
var min = this.dynamics_.findMin();
var max = this.dynamics_.findMax();
if (max != null && addr < (max.key + max.value.size) && addr >= min.key) {
var dynaEntry = this.findInTree_(this.dynamics_, addr);
if (dynaEntry == null) return null;
// Dedupe entry name.
var entry = dynaEntry.value;
if (!entry.nameUpdated_) {
entry.name = this.dynamicsNameGen_.getName(entry.name);
entry.nameUpdated_ = true;
}
return { entry : entry, offset : addr - dynaEntry.key };
}
return null;
};
/**
* Finds a code entry that contains the specified address. Both static and
* dynamic code entries are considered.
*
* @param {number} addr Address.
*/
CodeMap.prototype.findEntry = function(addr) {
var result = this.findAddress(addr);
return result ? result.entry : null;
};
/**
* Returns a dynamic code entry using its starting address.
*
* @param {number} addr Address.
*/
CodeMap.prototype.findDynamicEntryByStartAddress =
function(addr) {
var node = this.dynamics_.find(addr);
return node ? node.value : null;
};
/**
* Returns an array of all dynamic code entries.
*/
CodeMap.prototype.getAllDynamicEntries = function() {
return this.dynamics_.exportValues();
};
/**
* Returns an array of pairs of all dynamic code entries and their addresses.
*/
CodeMap.prototype.getAllDynamicEntriesWithAddresses = function() {
return this.dynamics_.exportKeysAndValues();
};
/**
* Returns an array of all static code entries.
*/
CodeMap.prototype.getAllStaticEntries = function() {
return this.statics_.exportValues();
};
/**
* Returns an array of pairs of all static code entries and their addresses.
*/
CodeMap.prototype.getAllStaticEntriesWithAddresses = function() {
return this.statics_.exportKeysAndValues();
};
/**
* Returns an array of all libraries entries.
*/
CodeMap.prototype.getAllLibrariesEntries = function() {
return this.libraries_.exportValues();
};
/**
* Creates a code entry object.
*
* @param {number} size Code entry size in bytes.
* @param {string} opt_name Code entry name.
* @param {string} opt_type Code entry type, e.g. SHARED_LIB, CPP.
* @constructor
*/
CodeMap.CodeEntry = function(size, opt_name, opt_type) {
this.size = size;
this.name = opt_name || '';
this.type = opt_type || '';
this.nameUpdated_ = false;
};
CodeMap.CodeEntry.prototype.getName = function() {
return this.name;
};
CodeMap.CodeEntry.prototype.toString = function() {
return this.name + ': ' + this.size.toString(16);
};
CodeMap.NameGenerator = function() {
this.knownNames_ = {};
};
CodeMap.NameGenerator.prototype.getName = function(name) {
if (!(name in this.knownNames_)) {
this.knownNames_[name] = 0;
return name;
}
var count = ++this.knownNames_[name];
return name + ' {' + count + '}';
};
// Copyright 2009 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.
/**
* Constructs a ConsArray object. It is used mainly for tree traversal.
* In this use case we have lots of arrays that we need to iterate
* sequentally. The internal Array implementation is horribly slow
* when concatenating on large (10K items) arrays due to memory copying.
* That's why we avoid copying memory and insead build a linked list
* of arrays to iterate through.
*
* @constructor
*/
export function ConsArray() {
this.tail_ = new ConsArray.Cell(null, null);
this.currCell_ = this.tail_;
this.currCellPos_ = 0;
};
/**
* Concatenates another array for iterating. Empty arrays are ignored.
* This operation can be safely performed during ongoing ConsArray
* iteration.
*
* @param {Array} arr Array to concatenate.
*/
ConsArray.prototype.concat = function(arr) {
if (arr.length > 0) {
this.tail_.data = arr;
this.tail_ = this.tail_.next = new ConsArray.Cell(null, null);
}
};
/**
* Whether the end of iteration is reached.
*/
ConsArray.prototype.atEnd = function() {
return this.currCell_ === null ||
this.currCell_.data === null ||
this.currCellPos_ >= this.currCell_.data.length;
};
/**
* Returns the current item, moves to the next one.
*/
ConsArray.prototype.next = function() {
var result = this.currCell_.data[this.currCellPos_++];
if (this.currCellPos_ >= this.currCell_.data.length) {
this.currCell_ = this.currCell_.next;
this.currCellPos_ = 0;
}
return result;
};
/**
* A cell object used for constructing a list in ConsArray.
*
* @constructor
*/
ConsArray.Cell = function(data, next) {
this.data = data;
this.next = next;
};
// Copyright 2009 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.
/**
* Creates a CSV lines parser.
*/
export class CsvParser {
/**
* Converts \x00 and \u0000 escape sequences in the given string.
*
* @param {string} input field.
**/
escapeField(string) {
let nextPos = string.indexOf("\\");
if (nextPos === -1) return string;
let result = string.substring(0, nextPos);
// Escape sequences of the form \x00 and \u0000;
let endPos = string.length;
let pos = 0;
while (nextPos !== -1) {
let escapeIdentifier = string.charAt(nextPos + 1);
pos = nextPos + 2;
if (escapeIdentifier === 'n') {
result += '\n';
nextPos = pos;
} else if (escapeIdentifier === '\\') {
result += '\\';
nextPos = pos;
} else {
if (escapeIdentifier === 'x') {
// \x00 ascii range escapes consume 2 chars.
nextPos = pos + 2;
} else {
// \u0000 unicode range escapes consume 4 chars.
nextPos = pos + 4;
}
// Convert the selected escape sequence to a single character.
let escapeChars = string.substring(pos, nextPos);
result += String.fromCharCode(parseInt(escapeChars, 16));
}
// Continue looking for the next escape sequence.
pos = nextPos;
nextPos = string.indexOf("\\", pos);
// If there are no more escape sequences consume the rest of the string.
if (nextPos === -1) {
result += string.substr(pos);
} else if (pos !== nextPos) {
result += string.substring(pos, nextPos);
}
}
return result;
}
/**
* Parses a line of CSV-encoded values. Returns an array of fields.
*
* @param {string} line Input line.
*/
parseLine(line) {
var pos = 0;
var endPos = line.length;
var fields = [];
if (endPos == 0) return fields;
let nextPos = 0;
while(nextPos !== -1) {
nextPos = line.indexOf(',', pos);
let field;
if (nextPos === -1) {
field = line.substr(pos);
} else {
field = line.substring(pos, nextPos);
}
fields.push(this.escapeField(field));
pos = nextPos + 1;
};
return fields
}
}
......@@ -19,9 +19,7 @@ def is_file_executable(fPath):
return os.path.isfile(fPath) and os.access(fPath, os.X_OK)
if __name__ == '__main__':
JS_FILES = ['splaytree.js', 'codemap.js', 'csvparser.js', 'consarray.js',
'profile.js', 'logreader.js', 'arguments.js', 'tickprocessor.js',
'SourceMap.js', 'dumpcpp.js', 'dumpcpp-driver.js']
JS_FILES = ['dumpcpp-driver.mjs']
tools_path = os.path.dirname(os.path.realpath(__file__))
on_windows = platform.system() == 'Windows'
JS_FILES = [os.path.join(tools_path, f) for f in JS_FILES]
......@@ -53,7 +51,7 @@ if __name__ == '__main__':
print('No d8 binary path found in {}.'.format(log_file))
sys.exit(-1)
args = [d8_exec] + JS_FILES + ['--'] + args
args = [d8_exec] + ['--module'] + JS_FILES + ['--'] + args
with open(log_file) as f:
sp = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
......
......@@ -2,6 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import "./sourcemap.mjs";
import {
CppProcessor, ArgumentsProcessor, UnixCppEntriesProvider,
WindowsCppEntriesProvider, MacCppEntriesProvider
} from "./dumpcpp.mjs";
// Dump C++ symbols of shared library if possible
function processArguments(args) {
......
......@@ -2,7 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function CppProcessor(cppEntriesProvider, timedRange, pairwiseTimedRange) {
import { LogReader, parseString } from "./logreader.mjs";
import { CodeMap } from "./codemap.mjs";
export {
ArgumentsProcessor, UnixCppEntriesProvider,
WindowsCppEntriesProvider, MacCppEntriesProvider,
} from "./tickprocessor.mjs";
import { inherits } from "./tickprocessor.mjs";
export function CppProcessor(cppEntriesProvider, timedRange, pairwiseTimedRange) {
LogReader.call(this, {
'shared-library': { parsers: [parseString, parseInt, parseInt, parseInt],
processor: this.processSharedLibrary }
......
......@@ -49,16 +49,7 @@ code is governed by a BSD-style license that can be found in the LICENSE file.
padding: 0.5em 0 0.2em 0;
}
</style>
<script src="./splaytree.js"></script>
<script src="./codemap.js"></script>
<script src="./csvparser.js"></script>
<script src="./consarray.js"></script>
<script src="./profile.js"></script>
<script src="./profile_view.js"></script>
<script src="./logreader.js"></script>
<script src="./arguments.js"></script>
<script src="./ic-processor.js"></script>
<script src="./SourceMap.js"></script>
<script type="module" src="./ic-processor.js"></script>
<script>
"use strict"
......
......@@ -33,9 +33,5 @@ if [ ! -x "$d8_exec" ]; then
fi
# nm spits out 'no symbols found' messages to stderr.
cat $log_file | $d8_exec $tools_path/splaytree.js $tools_path/codemap.js \
$tools_path/csvparser.js $tools_path/consarray.js \
$tools_path/profile.js $tools_path/profile_view.js \
$tools_path/logreader.js $tools_path/arguments.js \
$tools_path/ic-processor.js $tools_path/SourceMap.js \
$tools_path/ic-processor-driver.js -- $@ 2>/dev/null
cat $log_file | $d8_exec \
--module $tools_path/ic-processor-driver.mjs -- $@ 2>/dev/null
......@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { IcProcessor, ArgumentsProcessor, readFile } from "./ic-processor.mjs";
import "./SourceMap.mjs";
function processArguments(args) {
var processor = new ArgumentsProcessor(args);
if (processor.parse()) {
......
......@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { LogReader, parseString, parseVarArgs } from "./logreader.mjs";
import { BaseArgumentsProcessor } from "./arguments.mjs";
import { Profile } from "./profile.mjs";
function inherits(childCtor, parentCtor) {
childCtor.prototype.__proto__ = parentCtor.prototype;
};
......@@ -9,7 +13,7 @@ function inherits(childCtor, parentCtor) {
/**
* A thin wrapper around shell's 'read' function showing a file name on error.
*/
function readFile(fileName) {
export function readFile(fileName) {
try {
return read(fileName);
} catch (e) {
......@@ -31,7 +35,7 @@ function parseState(s) {
}
function IcProcessor() {
export function IcProcessor() {
var propertyICParser = [
parseInt, parseInt, parseInt, parseInt, parseString, parseString,
parseInt, parseString, parseString, parseString];
......@@ -175,7 +179,7 @@ print(
class ArgumentsProcessor extends BaseArgumentsProcessor {
export class ArgumentsProcessor extends BaseArgumentsProcessor {
getArgsDispatch() {
return {
'--range': ['range', 'auto,auto',
......
......@@ -34,9 +34,4 @@ fi
# nm spits out 'no symbols found' messages to stderr.
cat $log_file | $d8_exec --enable-os-system \
$tools_path/splaytree.js $tools_path/codemap.js \
$tools_path/csvparser.js $tools_path/consarray.js \
$tools_path/profile.js $tools_path/profile_view.js \
$tools_path/logreader.js $tools_path/arguments.js \
$tools_path/tickprocessor.js $tools_path/SourceMap.js \
$tools_path/tickprocessor-driver.js -- $@ 2>/dev/null
--module $tools_path/tickprocessor-driver.mjs -- $@ 2>/dev/null
// Copyright 2011 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.
/**
* @fileoverview Log Reader is used to process log file produced by V8.
*/
import { CsvParser } from "./csvparser.mjs";
/**
* Base class for processing log files.
*
* @param {Array.<Object>} dispatchTable A table used for parsing and processing
* log records.
* @param {boolean} timedRange Ignore ticks outside timed range.
* @param {boolean} pairwiseTimedRange Ignore ticks outside pairs of timer
* markers.
* @constructor
*/
export function LogReader(dispatchTable, timedRange, pairwiseTimedRange) {
/**
* @type {Array.<Object>}
*/
this.dispatchTable_ = dispatchTable;
/**
* @type {boolean}
*/
this.timedRange_ = timedRange;
/**
* @type {boolean}
*/
this.pairwiseTimedRange_ = pairwiseTimedRange;
if (pairwiseTimedRange) {
this.timedRange_ = true;
}
/**
* Current line.
* @type {number}
*/
this.lineNum_ = 0;
/**
* CSV lines parser.
* @type {CsvParser}
*/
this.csvParser_ = new CsvParser();
/**
* Keeps track of whether we've seen a "current-time" tick yet.
* @type {boolean}
*/
this.hasSeenTimerMarker_ = false;
/**
* List of log lines seen since last "current-time" tick.
* @type {Array.<String>}
*/
this.logLinesSinceLastTimerMarker_ = [];
};
/**
* Used for printing error messages.
*
* @param {string} str Error message.
*/
LogReader.prototype.printError = function(str) {
// Do nothing.
};
/**
* Processes a portion of V8 profiler event log.
*
* @param {string} chunk A portion of log.
*/
LogReader.prototype.processLogChunk = function(chunk) {
this.processLog_(chunk.split('\n'));
};
/**
* Processes a line of V8 profiler event log.
*
* @param {string} line A line of log.
*/
LogReader.prototype.processLogLine = function(line) {
if (!this.timedRange_) {
this.processLogLine_(line);
return;
}
if (line.startsWith("current-time")) {
if (this.hasSeenTimerMarker_) {
this.processLog_(this.logLinesSinceLastTimerMarker_);
this.logLinesSinceLastTimerMarker_ = [];
// In pairwise mode, a "current-time" line ends the timed range.
if (this.pairwiseTimedRange_) {
this.hasSeenTimerMarker_ = false;
}
} else {
this.hasSeenTimerMarker_ = true;
}
} else {
if (this.hasSeenTimerMarker_) {
this.logLinesSinceLastTimerMarker_.push(line);
} else if (!line.startsWith("tick")) {
this.processLogLine_(line);
}
}
};
/**
* Processes stack record.
*
* @param {number} pc Program counter.
* @param {number} func JS Function.
* @param {Array.<string>} stack String representation of a stack.
* @return {Array.<number>} Processed stack.
*/
LogReader.prototype.processStack = function(pc, func, stack) {
var fullStack = func ? [pc, func] : [pc];
var prevFrame = pc;
for (var i = 0, n = stack.length; i < n; ++i) {
var frame = stack[i];
var firstChar = frame.charAt(0);
if (firstChar == '+' || firstChar == '-') {
// An offset from the previous frame.
prevFrame += parseInt(frame, 16);
fullStack.push(prevFrame);
// Filter out possible 'overflow' string.
} else if (firstChar != 'o') {
fullStack.push(parseInt(frame, 16));
} else {
this.printError("dropping: " + frame);
}
}
return fullStack;
};
/**
* Returns whether a particular dispatch must be skipped.
*
* @param {!Object} dispatch Dispatch record.
* @return {boolean} True if dispatch must be skipped.
*/
LogReader.prototype.skipDispatch = function(dispatch) {
return false;
};
// Parses dummy variable for readability;
export const parseString = 'parse-string';
export const parseVarArgs = 'parse-var-args';
/**
* Does a dispatch of a log record.
*
* @param {Array.<string>} fields Log record.
* @private
*/
LogReader.prototype.dispatchLogRow_ = function(fields) {
// Obtain the dispatch.
var command = fields[0];
var dispatch = this.dispatchTable_[command];
if (dispatch === undefined) return;
if (dispatch === null || this.skipDispatch(dispatch)) {
return;
}
// Parse fields.
var parsedFields = [];
for (var i = 0; i < dispatch.parsers.length; ++i) {
var parser = dispatch.parsers[i];
if (parser === parseString) {
parsedFields.push(fields[1 + i]);
} else if (typeof parser == 'function') {
parsedFields.push(parser(fields[1 + i]));
} else if (parser === parseVarArgs) {
// var-args
parsedFields.push(fields.slice(1 + i));
break;
} else {
throw new Error("Invalid log field parser: " + parser);
}
}
// Run the processor.
dispatch.processor.apply(this, parsedFields);
};
/**
* Processes log lines.
*
* @param {Array.<string>} lines Log lines.
* @private
*/
LogReader.prototype.processLog_ = function(lines) {
for (var i = 0, n = lines.length; i < n; ++i) {
this.processLogLine_(lines[i]);
}
}
/**
* Processes a single log line.
*
* @param {String} a log line
* @private
*/
LogReader.prototype.processLogLine_ = function(line) {
if (line.length > 0) {
try {
var fields = this.csvParser_.parseLine(line);
this.dispatchLogRow_(fields);
} catch (e) {
this.printError('line ' + (this.lineNum_ + 1) + ': ' + (e.message || e) + '\n' + e.stack);
}
}
this.lineNum_++;
};
......@@ -33,9 +33,5 @@ if [ ! -x "$d8_exec" ]; then
fi
# nm spits out 'no symbols found' messages to stderr.
cat $log_file | $d8_exec $tools_path/splaytree.js $tools_path/codemap.js \
$tools_path/csvparser.js $tools_path/consarray.js \
$tools_path/profile.js $tools_path/profile_view.js \
$tools_path/logreader.js $tools_path/arguments.js \
$tools_path/map-processor.js $tools_path/SourceMap.js \
$tools_path/map-processor-driver.js -- $@ 2>/dev/null
cat $log_file | $d8_exec \
--module $tools_path/map-processor-driver.mjs -- $@ 2>/dev/null
......@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import "./SourceMap.mjs";
import {
MapProcessor, ArgumentsProcessor, readFile
} from "./map-processor.mjs";
function processArguments(args) {
var processor = new ArgumentsProcessor(args);
if (processor.parse()) {
......
......@@ -374,16 +374,7 @@ dd {
}
</style>
<script src="./splaytree.js"></script>
<script src="./codemap.js"></script>
<script src="./csvparser.js"></script>
<script src="./consarray.js"></script>
<script src="./profile.js"></script>
<script src="./profile_view.js"></script>
<script src="./logreader.js"></script>
<script src="./SourceMap.js"></script>
<script src="./arguments.js"></script>
<script src="./map-processor.js"></script>
<script type="module" src="./map-processor.js"></script>
<script>
"use strict"
// =========================================================================
......
......@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { LogReader, parseString, parseVarArgs } from "./logreader.mjs";
import { BaseArgumentsProcessor } from "./arguments.mjs";
import { Profile } from "./profile.mjs";
// ===========================================================================
function define(prototype, name, fn) {
Object.defineProperty(prototype, name, {value:fn, enumerable:false});
......@@ -18,9 +22,22 @@ define(Array.prototype, "max", function(fn) {
})
define(Array.prototype, "first", function() { return this[0] });
define(Array.prototype, "last", function() { return this[this.length - 1] });
/**
* A thin wrapper around shell's 'read' function showing a file name on error.
*/
export function readFile(fileName) {
try {
return read(fileName);
} catch (e) {
console.log(fileName + ': ' + (e.message || e));
throw e;
}
}
// ===========================================================================
class MapProcessor extends LogReader {
export class MapProcessor extends LogReader {
constructor() {
super();
this.dispatchTable_ = {
......@@ -745,7 +762,7 @@ function BreakDown(list, map_fn) {
// ===========================================================================
class ArgumentsProcessor extends BaseArgumentsProcessor {
export class ArgumentsProcessor extends BaseArgumentsProcessor {
getArgsDispatch() {
return {
'--range': ['range', 'auto,auto',
......
......@@ -34,9 +34,4 @@ fi
# nm spits out 'no symbols found' messages to stderr.
cat $log_file | $d8_exec --allow-natives-syntax \
$tools_path/splaytree.js $tools_path/codemap.js \
$tools_path/csvparser.js $tools_path/consarray.js \
$tools_path/profile.js $tools_path/profile_view.js \
$tools_path/logreader.js $tools_path/arguments.js \
$tools_path/parse-processor.js $tools_path/SourceMap.js \
$tools_path/parse-processor-driver.js -- $@ 2>/dev/null
--module $tools_path/parse-processor-driver.mjs -- $@ 2>/dev/null
......@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { WebInspector } from "./SourceMap.mjs";
import {
ParseProcessor, ArgumentsProcessor, readFile,
} from "./parse-processor.mjs";
function processArguments(args) {
var processor = new ArgumentsProcessor(args);
if (processor.parse()) {
......
......@@ -103,26 +103,22 @@ code is governed by a BSD-style license that can be found in the LICENSE file.
text-align: right;
}
</style>
<script src="./splaytree.js"></script>
<script src="./codemap.js"></script>
<script src="./csvparser.js"></script>
<script src="./consarray.js"></script>
<script src="./profile.js"></script>
<script src="./profile_view.js"></script>
<script src="./logreader.js"></script>
<script src="./arguments.js"></script>
<script src="./parse-processor.js"></script>
<script src="./SourceMap.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script>
"use strict";
<script type="module">
import { ParseProcessor, kSecondsToMillis } from "./parse-processor.mjs";
google.charts.load('current', {packages: ['corechart']});
function $(query) {
return document.querySelector(query);
}
function loadFile() {
window.addEventListener('DOMContentLoaded', (event) => {
$("#uploadInput").focus();
});
document.loadFile = function() {
let files = $('#uploadInput').files;
let file = files[0];
......@@ -140,10 +136,6 @@ function loadFile() {
reader.readAsText(file);
}
function handleOnLoad() {
document.querySelector("#uploadInput").focus();
}
function createNode(tag, classNames) {
let node = document.createElement(tag);
if (classNames) {
......@@ -395,7 +387,7 @@ function createFunktionList(metric, description, time, funktions) {
</script>
</head>
<body onload="handleOnLoad()">
<body>
<h1>BEHOLD, THIS IS PARSEROR!</h1>
<h2>Usage</h2>
......
......@@ -3,11 +3,13 @@
// found in the LICENSE file.
"use strict";
import { LogReader, parseString } from "./logreader.mjs";
import { BaseArgumentsProcessor } from "./arguments.mjs";
/**
* A thin wrapper around shell's 'read' function showing a file name on error.
*/
function readFile(fileName) {
export function readFile(fileName) {
try {
return read(fileName);
} catch (e) {
......@@ -730,8 +732,8 @@ class Funktion extends CompilationUnit {
// ===========================================================================
const kTimestampFactor = 1000;
const kSecondsToMillis = 1000;
export const kTimestampFactor = 1000;
export const kSecondsToMillis = 1000;
function toTimestamp(microseconds) {
return microseconds / kTimestampFactor
......@@ -744,7 +746,7 @@ function startOf(timestamp, time) {
}
class ParseProcessor extends LogReader {
export class ParseProcessor extends LogReader {
constructor() {
super();
this.dispatchTable_ = {
......@@ -1130,7 +1132,7 @@ class ParseProcessor extends LogReader {
}
class ArgumentsProcessor extends BaseArgumentsProcessor {
export class ArgumentsProcessor extends BaseArgumentsProcessor {
getArgsDispatch() {
return {};
}
......
This diff is collapsed.
// Copyright 2009 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.
import { ConsArray } from "./consarray.mjs";
/**
* Creates a Profile View builder object.
*
* @param {number} samplingRate Number of ms between profiler ticks.
* @constructor
*/
export function ViewBuilder(samplingRate) {
this.samplingRate = samplingRate;
};
/**
* Builds a profile view for the specified call tree.
*
* @param {CallTree} callTree A call tree.
* @param {boolean} opt_bottomUpViewWeights Whether remapping
* of self weights for a bottom up view is needed.
*/
ViewBuilder.prototype.buildView = function(
callTree, opt_bottomUpViewWeights) {
var head;
var samplingRate = this.samplingRate;
var createViewNode = this.createViewNode;
callTree.traverse(function(node, viewParent) {
var totalWeight = node.totalWeight * samplingRate;
var selfWeight = node.selfWeight * samplingRate;
if (opt_bottomUpViewWeights === true) {
if (viewParent === head) {
selfWeight = totalWeight;
} else {
selfWeight = 0;
}
}
var viewNode = createViewNode(node.label, totalWeight, selfWeight, head);
if (viewParent) {
viewParent.addChild(viewNode);
} else {
head = viewNode;
}
return viewNode;
});
var view = this.createView(head);
return view;
};
/**
* Factory method for a profile view.
*
* @param {ProfileView.Node} head View head node.
* @return {ProfileView} Profile view.
*/
ViewBuilder.prototype.createView = function(head) {
return new ProfileView(head);
};
/**
* Factory method for a profile view node.
*
* @param {string} internalFuncName A fully qualified function name.
* @param {number} totalTime Amount of time that application spent in the
* corresponding function and its descendants (not that depending on
* profile they can be either callees or callers.)
* @param {number} selfTime Amount of time that application spent in the
* corresponding function only.
* @param {ProfileView.Node} head Profile view head.
* @return {ProfileView.Node} Profile view node.
*/
ViewBuilder.prototype.createViewNode = function(
funcName, totalTime, selfTime, head) {
return new ProfileView.Node(
funcName, totalTime, selfTime, head);
};
/**
* Creates a Profile View object. It allows to perform sorting
* and filtering actions on the profile.
*
* @param {ProfileView.Node} head Head (root) node.
* @constructor
*/
export function ProfileView(head) {
this.head = head;
};
/**
* Sorts the profile view using the specified sort function.
*
* @param {function(ProfileView.Node,
* ProfileView.Node):number} sortFunc A sorting
* functions. Must comply with Array.sort sorting function requirements.
*/
ProfileView.prototype.sort = function(sortFunc) {
this.traverse(function (node) {
node.sortChildren(sortFunc);
});
};
/**
* Traverses profile view nodes in preorder.
*
* @param {function(ProfileView.Node)} f Visitor function.
*/
ProfileView.prototype.traverse = function(f) {
var nodesToTraverse = new ConsArray();
nodesToTraverse.concat([this.head]);
while (!nodesToTraverse.atEnd()) {
var node = nodesToTraverse.next();
f(node);
nodesToTraverse.concat(node.children);
}
};
/**
* Constructs a Profile View node object. Each node object corresponds to
* a function call.
*
* @param {string} internalFuncName A fully qualified function name.
* @param {number} totalTime Amount of time that application spent in the
* corresponding function and its descendants (not that depending on
* profile they can be either callees or callers.)
* @param {number} selfTime Amount of time that application spent in the
* corresponding function only.
* @param {ProfileView.Node} head Profile view head.
* @constructor
*/
ProfileView.Node = function(
internalFuncName, totalTime, selfTime, head) {
this.internalFuncName = internalFuncName;
this.totalTime = totalTime;
this.selfTime = selfTime;
this.head = head;
this.parent = null;
this.children = [];
};
/**
* Returns a share of the function's total time in its parent's total time.
*/
ProfileView.Node.prototype.__defineGetter__(
'parentTotalPercent',
function() { return this.totalTime /
(this.parent ? this.parent.totalTime : this.totalTime) * 100.0; });
/**
* Adds a child to the node.
*
* @param {ProfileView.Node} node Child node.
*/
ProfileView.Node.prototype.addChild = function(node) {
node.parent = this;
this.children.push(node);
};
/**
* Sorts all the node's children recursively.
*
* @param {function(ProfileView.Node,
* ProfileView.Node):number} sortFunc A sorting
* functions. Must comply with Array.sort sorting function requirements.
*/
ProfileView.Node.prototype.sortChildren = function(
sortFunc) {
this.children.sort(sortFunc);
};
// Copyright 2009 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.
/**
* Constructs a Splay tree. A splay tree is a self-balancing binary
* search tree with the additional property that recently accessed
* elements are quick to access again. It performs basic operations
* such as insertion, look-up and removal in O(log(n)) amortized time.
*
* @constructor
*/
export function SplayTree() {
};
/**
* Pointer to the root node of the tree.
*
* @type {SplayTree.Node}
* @private
*/
SplayTree.prototype.root_ = null;
/**
* @return {boolean} Whether the tree is empty.
*/
SplayTree.prototype.isEmpty = function() {
return !this.root_;
};
/**
* Inserts a node into the tree with the specified key and value if
* the tree does not already contain a node with the specified key. If
* the value is inserted, it becomes the root of the tree.
*
* @param {number} key Key to insert into the tree.
* @param {*} value Value to insert into the tree.
*/
SplayTree.prototype.insert = function(key, value) {
if (this.isEmpty()) {
this.root_ = new SplayTree.Node(key, value);
return;
}
// Splay on the key to move the last node on the search path for
// the key to the root of the tree.
this.splay_(key);
if (this.root_.key == key) {
return;
}
var node = new SplayTree.Node(key, value);
if (key > this.root_.key) {
node.left = this.root_;
node.right = this.root_.right;
this.root_.right = null;
} else {
node.right = this.root_;
node.left = this.root_.left;
this.root_.left = null;
}
this.root_ = node;
};
/**
* Removes a node with the specified key from the tree if the tree
* contains a node with this key. The removed node is returned. If the
* key is not found, an exception is thrown.
*
* @param {number} key Key to find and remove from the tree.
* @return {SplayTree.Node} The removed node.
*/
SplayTree.prototype.remove = function(key) {
if (this.isEmpty()) {
throw Error('Key not found: ' + key);
}
this.splay_(key);
if (this.root_.key != key) {
throw Error('Key not found: ' + key);
}
var removed = this.root_;
if (!this.root_.left) {
this.root_ = this.root_.right;
} else {
var right = this.root_.right;
this.root_ = this.root_.left;
// Splay to make sure that the new root has an empty right child.
this.splay_(key);
// Insert the original right child as the right child of the new
// root.
this.root_.right = right;
}
return removed;
};
/**
* Returns the node having the specified key or null if the tree doesn't contain
* a node with the specified key.
*
* @param {number} key Key to find in the tree.
* @return {SplayTree.Node} Node having the specified key.
*/
SplayTree.prototype.find = function(key) {
if (this.isEmpty()) {
return null;
}
this.splay_(key);
return this.root_.key == key ? this.root_ : null;
};
/**
* @return {SplayTree.Node} Node having the minimum key value.
*/
SplayTree.prototype.findMin = function() {
if (this.isEmpty()) {
return null;
}
var current = this.root_;
while (current.left) {
current = current.left;
}
return current;
};
/**
* @return {SplayTree.Node} Node having the maximum key value.
*/
SplayTree.prototype.findMax = function(opt_startNode) {
if (this.isEmpty()) {
return null;
}
var current = opt_startNode || this.root_;
while (current.right) {
current = current.right;
}
return current;
};
/**
* @return {SplayTree.Node} Node having the maximum key value that
* is less or equal to the specified key value.
*/
SplayTree.prototype.findGreatestLessThan = function(key) {
if (this.isEmpty()) {
return null;
}
// Splay on the key to move the node with the given key or the last
// node on the search path to the top of the tree.
this.splay_(key);
// Now the result is either the root node or the greatest node in
// the left subtree.
if (this.root_.key <= key) {
return this.root_;
} else if (this.root_.left) {
return this.findMax(this.root_.left);
} else {
return null;
}
};
/**
* @return {Array<*>} An array containing all the values of tree's nodes paired
* with keys.
*/
SplayTree.prototype.exportKeysAndValues = function() {
var result = [];
this.traverse_(function(node) { result.push([node.key, node.value]); });
return result;
};
/**
* @return {Array<*>} An array containing all the values of tree's nodes.
*/
SplayTree.prototype.exportValues = function() {
var result = [];
this.traverse_(function(node) { result.push(node.value); });
return result;
};
/**
* Perform the splay operation for the given key. Moves the node with
* the given key to the top of the tree. If no node has the given
* key, the last node on the search path is moved to the top of the
* tree. This is the simplified top-down splaying algorithm from:
* "Self-adjusting Binary Search Trees" by Sleator and Tarjan
*
* @param {number} key Key to splay the tree on.
* @private
*/
SplayTree.prototype.splay_ = function(key) {
if (this.isEmpty()) {
return;
}
// Create a dummy node. The use of the dummy node is a bit
// counter-intuitive: The right child of the dummy node will hold
// the L tree of the algorithm. The left child of the dummy node
// will hold the R tree of the algorithm. Using a dummy node, left
// and right will always be nodes and we avoid special cases.
var dummy, left, right;
dummy = left = right = new SplayTree.Node(null, null);
var current = this.root_;
while (true) {
if (key < current.key) {
if (!current.left) {
break;
}
if (key < current.left.key) {
// Rotate right.
var tmp = current.left;
current.left = tmp.right;
tmp.right = current;
current = tmp;
if (!current.left) {
break;
}
}
// Link right.
right.left = current;
right = current;
current = current.left;
} else if (key > current.key) {
if (!current.right) {
break;
}
if (key > current.right.key) {
// Rotate left.
var tmp = current.right;
current.right = tmp.left;
tmp.left = current;
current = tmp;
if (!current.right) {
break;
}
}
// Link left.
left.right = current;
left = current;
current = current.right;
} else {
break;
}
}
// Assemble.
left.right = current.left;
right.left = current.right;
current.left = dummy.right;
current.right = dummy.left;
this.root_ = current;
};
/**
* Performs a preorder traversal of the tree.
*
* @param {function(SplayTree.Node)} f Visitor function.
* @private
*/
SplayTree.prototype.traverse_ = function(f) {
var nodesToVisit = [this.root_];
while (nodesToVisit.length > 0) {
var node = nodesToVisit.shift();
if (node == null) {
continue;
}
f(node);
nodesToVisit.push(node.left);
nodesToVisit.push(node.right);
}
};
/**
* Constructs a Splay tree node.
*
* @param {number} key Key.
* @param {*} value Value.
*/
SplayTree.Node = function(key, value) {
this.key = key;
this.value = value;
};
/**
* @type {SplayTree.Node}
*/
SplayTree.Node.prototype.left = null;
/**
* @type {SplayTree.Node}
*/
SplayTree.Node.prototype.right = null;
......@@ -12,17 +12,6 @@ found in the LICENSE file. -->
<!-- <link rel="icon" type="image/png" href="/images/favicon.png"/> -->
<script type="module" src="index.mjs"></script>
<link rel="stylesheet" type="text/css" href="./index.css">
<script type="module" src="helper.mjs"></script>
<script src="../splaytree.js"></script>
<script src="../codemap.js"></script>
<script src="../csvparser.js"></script>
<script src="../consarray.js"></script>
<script src="../profile.js"></script>
<script src="../profile_view.js"></script>
<script src="../logreader.js"></script>
<script src="../arguments.js"></script>
<script src="../SourceMap.js"></script>
<style>
#instructions {
padding: 10px 10px 60px 10px;
......
......@@ -2,17 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { SelectionEvent, FocusEvent, SelectTimeEvent } from "./events.mjs";
import { State } from "./app-model.mjs";
import { MapLogEvent } from "./log/map.mjs";
import { IcLogEvent } from "./log/ic.mjs";
import Processor from "./processor.mjs";
import { SourcePosition } from "../profile.mjs";
import { $ } from "./helper.mjs";
import "./ic-panel.mjs";
import "./timeline-panel.mjs";
import "./map-panel.mjs";
import "./log-file-reader.mjs";
import "./source-panel.mjs";
class App {
#state;
#view;
......
......@@ -4,8 +4,9 @@
import { MapLogEvent, Edge } from "./log/map.mjs";
import { IcLogEvent } from "./log/ic.mjs";
import { Timeline } from './timeline.mjs';
import { Timeline } from "./timeline.mjs";
import { LogReader, parseString, parseVarArgs } from "../logreader.mjs";
import { Profile } from "../profile.mjs";
// ===========================================================================
......
......@@ -42,24 +42,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -->
margin-top: 0px;
}
</style>
<script src="splaytree.js"></script>
<script src="codemap.js"></script>
<script src="csvparser.js"></script>
<script src="consarray.js"></script>
<script src="profile.js"></script>
<script src="profile_view.js"></script>
<script src="logreader.js"></script>
<script src="arguments.js"></script>
<script src="tickprocessor.js"></script>
<script>
<script type="module">
import {
TickProcessor, UnixCppEntriesProvider, MacCppEntriesProvider,
WindowsCppEntriesProvider
} from "./tickprocessor.mjs";
var v8log_content;
var textout;
globalThis.textout;
function load_logfile(evt) {
textout.value = "";
globalThis.load_logfile = function(evt) {
globalThis.textout.value = "";
var f = evt.target.files[0];
if (f) {
var reader = new FileReader();
......@@ -77,7 +70,7 @@ function load_logfile(evt) {
}
function print(arg) {
textout.value+=arg+"\n";
globalThis.textout.value+=arg+"\n";
}
function start_process() {
......@@ -108,11 +101,12 @@ function start_process() {
tickProcessor.processLogChunk(v8log_content);
tickProcessor.printStatistics();
}
</script>
<script>
function Load() {
document.getElementById('fileinput').addEventListener(
'change', load_logfile, false);
textout = document.getElementById('textout');
'change', globalThis.load_logfile, false);
globalThis.textout = document.getElementById('textout');
}
</script>
</head>
......
// Copyright 2012 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.
import { WebInspector} from "./sourcemap.mjs";
import {
ArgumentsProcessor, TickProcessor, UnixCppEntriesProvider,
WindowsCppEntriesProvider, MacCppEntriesProvider, readFile,
} from "./tickprocessor.mjs";
// Tick Processor's code flow.
function processArguments(args) {
var processor = new ArgumentsProcessor(args);
if (processor.parse()) {
return processor.result();
} else {
processor.printUsageAndExit();
}
}
function initSourceMapSupport() {
// Pull dev tools source maps into our name space.
SourceMap = WebInspector.SourceMap;
// Overwrite the load function to load scripts synchronously.
SourceMap.load = function(sourceMapURL) {
var content = readFile(sourceMapURL);
var sourceMapObject = (JSON.parse(content));
return new SourceMap(sourceMapURL, sourceMapObject);
};
}
var entriesProviders = {
'unix': UnixCppEntriesProvider,
'windows': WindowsCppEntriesProvider,
'mac': MacCppEntriesProvider
};
var params = processArguments(arguments);
var sourceMap = null;
if (params.sourceMap) {
initSourceMapSupport();
sourceMap = SourceMap.load(params.sourceMap);
}
var tickProcessor = new TickProcessor(
new (entriesProviders[params.platform])(params.nm, params.objdump, params.targetRootFS,
params.apkEmbeddedLibrary),
params.separateIc,
params.separateBytecodes,
params.separateBuiltins,
params.separateStubs,
params.callGraphSize,
params.ignoreUnknown,
params.stateFilter,
params.distortion,
params.range,
sourceMap,
params.timedRange,
params.pairwiseTimedRange,
params.onlySummary,
params.runtimeTimerFilter,
params.preprocessJson);
tickProcessor.processLogFile(params.logFileName);
tickProcessor.printStatistics();
This diff is collapsed.
......@@ -27,4 +27,4 @@ IF NOT %arg8:~0,2% == 8 (IF NOT %arg8:~0,2% == 8- SET log_file=%8)
SET arg9=9%9
IF NOT %arg9:~0,2% == 9 (IF NOT %arg9:~0,2% == 9- SET log_file=%9)
type %log_file% | %D8_PATH%\d8 %tools_dir%splaytree.js %tools_dir%codemap.js %tools_dir%csvparser.js %tools_dir%consarray.js %tools_dir%profile.js %tools_dir%profile_view.js %tools_dir%logreader.js %tools_dir%SourceMap.js %tools_dir%arguments.js %tools_dir%tickprocessor.js %tools_dir%tickprocessor-driver.js -- --windows %*
type %log_file% | %D8_PATH%\d8 --module %tools_dir%tickprocessor-driver.js -- --windows %*
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment