Commit d5d45c61 authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[tools] Migrate more tools to ES6 classes

For simplicity this CL includes a first crude conversion of
tickprocessor.mjs. Later CLs will introduce more ES6 syntax and clean
up more code.

Bug: v8:10667
Change-Id: Ief2ca623f5562114fb976a95d156e2ab3f961114
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2611252Reviewed-by: 's avatarSathya Gunasekaran  <gsathya@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72013}
parent 73875e95
...@@ -36,49 +36,47 @@ ...@@ -36,49 +36,47 @@
* *
* @constructor * @constructor
*/ */
export function ConsArray() { export class ConsArray {
this.tail_ = new ConsArray.Cell(null, null); constructor() {
this.currCell_ = this.tail_; this.tail_ = new ConsArrayCell(null, null);
this.currCellPos_ = 0; this.currCell_ = this.tail_;
}; this.currCellPos_ = 0;
}
/**
/** * Concatenates another array for iterating. Empty arrays are ignored.
* Concatenates another array for iterating. Empty arrays are ignored. * This operation can be safely performed during ongoing ConsArray
* This operation can be safely performed during ongoing ConsArray * iteration.
* iteration. *
* * @param {Array} arr Array to concatenate.
* @param {Array} arr Array to concatenate. */
*/ concat(arr) {
ConsArray.prototype.concat = function(arr) { if (arr.length > 0) {
if (arr.length > 0) { this.tail_.data = arr;
this.tail_.data = arr; this.tail_ = this.tail_.next = new ConsArrayCell(null, null);
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;
};
/**
* Whether the end of iteration is reached.
*/
atEnd() {
return this.currCell_ === null ||
this.currCell_.data === null ||
this.currCellPos_ >= this.currCell_.data.length;
}
/** /**
* Returns the current item, moves to the next one. * Returns the current item, moves to the next one.
*/ */
ConsArray.prototype.next = function() { next() {
const result = this.currCell_.data[this.currCellPos_++]; const result = this.currCell_.data[this.currCellPos_++];
if (this.currCellPos_ >= this.currCell_.data.length) { if (this.currCellPos_ >= this.currCell_.data.length) {
this.currCell_ = this.currCell_.next; this.currCell_ = this.currCell_.next;
this.currCellPos_ = 0; this.currCellPos_ = 0;
}
return result;
} }
return result; }
};
/** /**
...@@ -86,7 +84,9 @@ ConsArray.prototype.next = function() { ...@@ -86,7 +84,9 @@ ConsArray.prototype.next = function() {
* *
* @constructor * @constructor
*/ */
ConsArray.Cell = function(data, next) { class ConsArrayCell {
this.data = data; constructor(data, next) {
this.next = next; this.data = data;
}; this.next = next;
}
}
...@@ -5,10 +5,9 @@ ...@@ -5,10 +5,9 @@
import { LogReader, parseString } from "./logreader.mjs"; import { LogReader, parseString } from "./logreader.mjs";
import { CodeMap, CodeEntry } from "./codemap.mjs"; import { CodeMap, CodeEntry } from "./codemap.mjs";
export { export {
ArgumentsProcessor, UnixCppEntriesProvider, ArgumentsProcessor, UnixCppEntriesProvider,
WindowsCppEntriesProvider, MacCppEntriesProvider, WindowsCppEntriesProvider, MacCppEntriesProvider,
} from "./tickprocessor.mjs"; } from "./tickprocessor.mjs";
import { inherits } from "./tickprocessor.mjs";
export class CppProcessor extends LogReader { export class CppProcessor extends LogReader {
...@@ -29,7 +28,7 @@ export class CppProcessor extends LogReader { ...@@ -29,7 +28,7 @@ export class CppProcessor extends LogReader {
*/ */
printError(str) { printError(str) {
print(str); print(str);
}; }
processLogFile(fileName) { processLogFile(fileName) {
this.lastLogFileName_ = fileName; this.lastLogFileName_ = fileName;
...@@ -37,14 +36,14 @@ export class CppProcessor extends LogReader { ...@@ -37,14 +36,14 @@ export class CppProcessor extends LogReader {
while (line = readline()) { while (line = readline()) {
this.processLogLine(line); this.processLogLine(line);
} }
}; }
processLogFileInTest(fileName) { processLogFileInTest(fileName) {
// Hack file name to avoid dealing with platform specifics. // Hack file name to avoid dealing with platform specifics.
this.lastLogFileName_ = 'v8.log'; this.lastLogFileName_ = 'v8.log';
const contents = readFile(fileName); const contents = readFile(fileName);
this.processLogChunk(contents); this.processLogChunk(contents);
}; }
processSharedLibrary(name, startAddr, endAddr, aslrSlide) { processSharedLibrary(name, startAddr, endAddr, aslrSlide) {
const self = this; const self = this;
...@@ -53,7 +52,7 @@ export class CppProcessor extends LogReader { ...@@ -53,7 +52,7 @@ export class CppProcessor extends LogReader {
const entry = new CodeEntry(fEnd - fStart, fName, 'CPP'); const entry = new CodeEntry(fEnd - fStart, fName, 'CPP');
self.codeMap_.addStaticCode(fStart, entry); self.codeMap_.addStaticCode(fStart, entry);
}); });
}; }
dumpCppSymbols() { dumpCppSymbols() {
const staticEntries = this.codeMap_.getAllStaticEntriesWithAddresses(); const staticEntries = this.codeMap_.getAllStaticEntriesWithAddresses();
......
...@@ -28,9 +28,13 @@ ...@@ -28,9 +28,13 @@
/** /**
* @fileoverview Log Reader is used to process log file produced by V8. * @fileoverview Log Reader is used to process log file produced by V8.
*/ */
import { CsvParser } from "./csvparser.mjs"; import { CsvParser } from "./csvparser.mjs";
// Parses dummy variable for readability;
export const parseString = 'parse-string';
export const parseVarArgs = 'parse-var-args';
/** /**
* Base class for processing log files. * Base class for processing log files.
* *
...@@ -41,206 +45,200 @@ ...@@ -41,206 +45,200 @@
* markers. * markers.
* @constructor * @constructor
*/ */
export function LogReader(dispatchTable, timedRange, pairwiseTimedRange) { export class LogReader {
/** constructor (dispatchTable, timedRange, pairwiseTimedRange) {
* @type {Array.<Object>} /**
*/ * @type {Array.<Object>}
this.dispatchTable_ = dispatchTable; */
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_ = [];
}
/** /**
* @type {boolean} * Used for printing error messages.
*
* @param {string} str Error message.
*/ */
this.timedRange_ = timedRange; printError(str) {
// Do nothing.
}
/** /**
* @type {boolean} * Processes a portion of V8 profiler event log.
*
* @param {string} chunk A portion of log.
*/ */
this.pairwiseTimedRange_ = pairwiseTimedRange; processLogChunk(chunk) {
if (pairwiseTimedRange) { this.processLog_(chunk.split('\n'));
this.timedRange_ = true;
} }
/** /**
* Current line. * Processes a line of V8 profiler event log.
* @type {number} *
* @param {string} line A line of log.
*/ */
this.lineNum_ = 0; processLogLine(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);
}
}
}
/** /**
* CSV lines parser. * Processes stack record.
* @type {CsvParser} *
* @param {number} pc Program counter.
* @param {number} func JS Function.
* @param {Array.<string>} stack String representation of a stack.
* @return {Array.<number>} Processed stack.
*/ */
this.csvParser_ = new CsvParser(); processStack(pc, func, stack) {
const fullStack = func ? [pc, func] : [pc];
let prevFrame = pc;
for (let i = 0, n = stack.length; i < n; ++i) {
const frame = stack[i];
const 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;
}
/** /**
* Keeps track of whether we've seen a "current-time" tick yet. * Returns whether a particular dispatch must be skipped.
* @type {boolean} *
* @param {!Object} dispatch Dispatch record.
* @return {boolean} True if dispatch must be skipped.
*/ */
this.hasSeenTimerMarker_ = false; skipDispatch(dispatch) {
return false;
}
/** /**
* List of log lines seen since last "current-time" tick. * Does a dispatch of a log record.
* @type {Array.<String>} *
* @param {Array.<string>} fields Log record.
* @private
*/ */
this.logLinesSinceLastTimerMarker_ = []; dispatchLogRow_(fields) {
}; // Obtain the dispatch.
const command = fields[0];
const dispatch = this.dispatchTable_[command];
/** if (dispatch === undefined) return;
* Used for printing error messages. if (dispatch === null || this.skipDispatch(dispatch)) {
* return;
* @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);
}
}
};
// Parse fields.
/** const parsedFields = [];
* Processes stack record. for (let i = 0; i < dispatch.parsers.length; ++i) {
* const parser = dispatch.parsers[i];
* @param {number} pc Program counter. if (parser === parseString) {
* @param {number} func JS Function. parsedFields.push(fields[1 + i]);
* @param {Array.<string>} stack String representation of a stack. } else if (typeof parser == 'function') {
* @return {Array.<number>} Processed stack. parsedFields.push(parser(fields[1 + i]));
*/ } else if (parser === parseVarArgs) {
LogReader.prototype.processStack = function(pc, func, stack) { // var-args
const fullStack = func ? [pc, func] : [pc]; parsedFields.push(fields.slice(1 + i));
let prevFrame = pc; break;
for (let i = 0, n = stack.length; i < n; ++i) { } else {
const frame = stack[i]; throw new Error(`Invalid log field parser: ${parser}`);
const 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;
};
// Run the processor.
/** dispatch.processor.apply(this, parsedFields);
* Returns whether a particular dispatch must be skipped.
*
* @param {!Object} dispatch Dispatch record.
* @return {boolean} True if dispatch must be skipped.
*/
LogReader.prototype.skipDispatch = dispatch => 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.
const command = fields[0];
const dispatch = this.dispatchTable_[command];
if (dispatch === undefined) return;
if (dispatch === null || this.skipDispatch(dispatch)) {
return;
} }
// Parse fields. /**
const parsedFields = []; * Processes log lines.
for (let i = 0; i < dispatch.parsers.length; ++i) { *
const parser = dispatch.parsers[i]; * @param {Array.<string>} lines Log lines.
if (parser === parseString) { * @private
parsedFields.push(fields[1 + i]); */
} else if (typeof parser == 'function') { processLog_(lines) {
parsedFields.push(parser(fields[1 + i])); for (let i = 0, n = lines.length; i < n; ++i) {
} else if (parser === parseVarArgs) { this.processLogLine_(lines[i]);
// 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 a single log line.
}; *
* @param {String} a log line
* @private
/** */
* Processes log lines. processLogLine_(line) {
* if (line.length > 0) {
* @param {Array.<string>} lines Log lines. try {
* @private const fields = this.csvParser_.parseLine(line);
*/ this.dispatchLogRow_(fields);
LogReader.prototype.processLog_ = function(lines) { } catch (e) {
for (let i = 0, n = lines.length; i < n; ++i) { this.printError(`line ${this.lineNum_ + 1}: ${e.message || e}\n${e.stack}`);
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 {
const fields = this.csvParser_.parseLine(line);
this.dispatchLogRow_(fields);
} catch (e) {
this.printError(`line ${this.lineNum_ + 1}: ${e.message || e}\n${e.stack}`);
} }
this.lineNum_++;
} }
this.lineNum_++; }
};
...@@ -34,274 +34,250 @@ ...@@ -34,274 +34,250 @@
* *
* @constructor * @constructor
*/ */
export function SplayTree() { export class SplayTree {
};
/**
* Pointer to the root node of the tree.
/** *
* Pointer to the root node of the tree. * @type {SplayTreeNode}
* * @private
* @type {SplayTree.Node} */
* @private root_ = null;
*/
SplayTree.prototype.root_ = null;
/**
* @return {boolean} Whether the tree is empty.
/** */
* @return {boolean} Whether the tree is empty. isEmpty() {
*/ return !this.root_;
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;
}
const 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;
};
/**
* 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.
*/
insert(key, value) {
if (this.isEmpty()) {
this.root_ = new SplayTreeNode(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;
/** const node = new SplayTreeNode(key, value);
* Removes a node with the specified key from the tree if the tree if (key > this.root_.key) {
* contains a node with this key. The removed node is returned. If the node.left = this.root_;
* key is not found, an exception is thrown. node.right = this.root_.right;
* this.root_.right = null;
* @param {number} key Key to find and remove from the tree. } else {
* @return {SplayTree.Node} The removed node. node.right = this.root_;
*/ node.left = this.root_.left;
SplayTree.prototype.remove = function(key) { this.root_.left = null;
if (this.isEmpty()) { }
throw Error(`Key not found: ${key}`); this.root_ = node;
}
this.splay_(key);
if (this.root_.key != key) {
throw Error(`Key not found: ${key}`);
} }
const removed = this.root_;
if (!this.root_.left) { /**
this.root_ = this.root_.right; * Removes a node with the specified key from the tree if the tree
} else { * contains a node with this key. The removed node is returned. If the
const { right } = this.root_; * key is not found, an exception is thrown.
this.root_ = this.root_.left; *
// Splay to make sure that the new root has an empty right child. * @param {number} key Key to find and remove from the tree.
* @return {SplayTreeNode} The removed node.
*/
remove(key) {
if (this.isEmpty()) {
throw Error(`Key not found: ${key}`);
}
this.splay_(key); this.splay_(key);
// Insert the original right child as the right child of the new if (this.root_.key != key) {
// root. throw Error(`Key not found: ${key}`);
this.root_.right = right; }
const removed = this.root_;
if (!this.root_.left) {
this.root_ = this.root_.right;
} else {
const { right } = this.root_;
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;
} }
return removed;
};
/**
/** * Returns the node having the specified key or null if the tree doesn't contain
* Returns the node having the specified key or null if the tree doesn't contain * a node with the specified key.
* a node with the specified key. *
* * @param {number} key Key to find in the tree.
* @param {number} key Key to find in the tree. * @return {SplayTreeNode} Node having the specified key.
* @return {SplayTree.Node} Node having the specified key. */
*/ find(key) {
SplayTree.prototype.find = function(key) { if (this.isEmpty()) return null;
if (this.isEmpty()) { this.splay_(key);
return null; return this.root_.key == key ? this.root_ : null;
} }
this.splay_(key);
return this.root_.key == key ? this.root_ : null;
};
/** /**
* @return {SplayTree.Node} Node having the minimum key value. * @return {SplayTreeNode} Node having the minimum key value.
*/ */
SplayTree.prototype.findMin = function() { findMin() {
if (this.isEmpty()) { if (this.isEmpty()) return null;
return null; let current = this.root_;
} while (current.left) {
let current = this.root_; current = current.left;
while (current.left) { }
current = current.left; return current;
} }
return current;
};
/** /**
* @return {SplayTree.Node} Node having the maximum key value. * @return {SplayTreeNode} Node having the maximum key value.
*/ */
SplayTree.prototype.findMax = function(opt_startNode) { findMax(opt_startNode) {
if (this.isEmpty()) { if (this.isEmpty()) return null;
return null; let current = opt_startNode || this.root_;
} while (current.right) {
let current = opt_startNode || this.root_; current = current.right;
while (current.right) { }
current = current.right; return current;
} }
return current;
};
/**
/** * @return {SplayTreeNode} Node having the maximum key value that
* @return {SplayTree.Node} Node having the maximum key value that * is less or equal to the specified key value.
* is less or equal to the specified key value. */
*/ findGreatestLessThan(key) {
SplayTree.prototype.findGreatestLessThan = function(key) { if (this.isEmpty()) return null;
if (this.isEmpty()) { // Splay on the key to move the node with the given key or the last
return null; // node on the search path to the top of the tree.
} this.splay_(key);
// Splay on the key to move the node with the given key or the last // Now the result is either the root node or the greatest node in
// node on the search path to the top of the tree. // the left subtree.
this.splay_(key); if (this.root_.key <= key) {
// Now the result is either the root node or the greatest node in return this.root_;
// the left subtree. } else if (this.root_.left) {
if (this.root_.key <= key) { return this.findMax(this.root_.left);
return this.root_; } else {
} else if (this.root_.left) { return null;
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() {
const 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() {
const result = [];
this.traverse_(function(node) { result.push(node.value); });
return result;
};
/**
* @return {Array<*>} An array containing all the values of tree's nodes paired
* with keys.
*/
exportKeysAndValues() {
const result = [];
this.traverse_(function(node) { result.push([node.key, node.value]); });
return result;
}
/** /**
* Perform the splay operation for the given key. Moves the node with * @return {Array<*>} An array containing all the values of tree's nodes.
* 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 exportValues() {
* tree. This is the simplified top-down splaying algorithm from: const result = [];
* "Self-adjusting Binary Search Trees" by Sleator and Tarjan this.traverse_(function(node) { result.push(node.value); });
* return result;
* @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 * Perform the splay operation for the given key. Moves the node with
// will hold the R tree of the algorithm. Using a dummy node, left * the given key to the top of the tree. If no node has the given
// and right will always be nodes and we avoid special cases. * key, the last node on the search path is moved to the top of the
let dummy, left, right; * tree. This is the simplified top-down splaying algorithm from:
dummy = left = right = new SplayTree.Node(null, null); * "Self-adjusting Binary Search Trees" by Sleator and Tarjan
let current = this.root_; *
while (true) { * @param {number} key Key to splay the tree on.
if (key < current.key) { * @private
if (!current.left) { */
break; splay_(key) {
} if (this.isEmpty()) return;
if (key < current.left.key) { // Create a dummy node. The use of the dummy node is a bit
// Rotate right. // counter-intuitive: The right child of the dummy node will hold
const tmp = current.left; // the L tree of the algorithm. The left child of the dummy node
current.left = tmp.right; // will hold the R tree of the algorithm. Using a dummy node, left
tmp.right = current; // and right will always be nodes and we avoid special cases.
current = tmp; let dummy, left, right;
dummy = left = right = new SplayTreeNode(null, null);
let current = this.root_;
while (true) {
if (key < current.key) {
if (!current.left) { if (!current.left) {
break; break;
} }
} if (key < current.left.key) {
// Link right. // Rotate right.
right.left = current; const tmp = current.left;
right = current; current.left = tmp.right;
current = current.left; tmp.right = current;
} else if (key > current.key) { current = tmp;
if (!current.right) { if (!current.left) {
break; break;
} }
if (key > current.right.key) { }
// Rotate left. // Link right.
const tmp = current.right; right.left = current;
current.right = tmp.left; right = current;
tmp.left = current; current = current.left;
current = tmp; } else if (key > current.key) {
if (!current.right) { if (!current.right) {
break; break;
} }
if (key > current.right.key) {
// Rotate left.
const 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;
} }
// 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;
} }
// 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. * Performs a preorder traversal of the tree.
* *
* @param {function(SplayTree.Node)} f Visitor function. * @param {function(SplayTreeNode)} f Visitor function.
* @private * @private
*/ */
SplayTree.prototype.traverse_ = function(f) { traverse_(f) {
const nodesToVisit = [this.root_]; const nodesToVisit = [this.root_];
while (nodesToVisit.length > 0) { while (nodesToVisit.length > 0) {
const node = nodesToVisit.shift(); const node = nodesToVisit.shift();
if (node == null) { if (node == null) {
continue; continue;
}
f(node);
nodesToVisit.push(node.left);
nodesToVisit.push(node.right);
} }
f(node);
nodesToVisit.push(node.left);
nodesToVisit.push(node.right);
} }
}; }
/** /**
* Constructs a Splay tree node. * Constructs a Splay tree node.
...@@ -309,19 +285,17 @@ SplayTree.prototype.traverse_ = function(f) { ...@@ -309,19 +285,17 @@ SplayTree.prototype.traverse_ = function(f) {
* @param {number} key Key. * @param {number} key Key.
* @param {*} value Value. * @param {*} value Value.
*/ */
SplayTree.Node = function(key, value) { class SplayTreeNode {
this.key = key; constructor(key, value) {
this.value = value; this.key = key;
}; this.value = value;
/**
* @type {SplayTreeNode}
/** */
* @type {SplayTree.Node} this.left = null;
*/ /**
SplayTree.Node.prototype.left = null; * @type {SplayTreeNode}
*/
this.right = null;
/** }
* @type {SplayTree.Node} };
*/ \ No newline at end of file
SplayTree.Node.prototype.right = null;
...@@ -31,11 +31,6 @@ import { Profile, JsonProfile } from "./profile.mjs"; ...@@ -31,11 +31,6 @@ import { Profile, JsonProfile } from "./profile.mjs";
import { ViewBuilder } from "./profile_view.mjs"; import { ViewBuilder } from "./profile_view.mjs";
export function inherits(childCtor, parentCtor) {
childCtor.prototype.__proto__ = parentCtor.prototype;
};
class V8Profile extends Profile { class V8Profile extends Profile {
static IC_RE = static IC_RE =
/^(LoadGlobalIC: )|(Handler: )|(?:CallIC|LoadIC|StoreIC)|(?:Builtin: (?:Keyed)?(?:Load|Store)IC_)/; /^(LoadGlobalIC: )|(Handler: )|(?:CallIC|LoadIC|StoreIC)|(?:Builtin: (?:Keyed)?(?:Load|Store)IC_)/;
...@@ -75,7 +70,8 @@ export function readFile(fileName) { ...@@ -75,7 +70,8 @@ export function readFile(fileName) {
} }
export function TickProcessor( export class TickProcessor extends LogReader {
constructor(
cppEntriesProvider, cppEntriesProvider,
separateIc, separateIc,
separateBytecodes, separateBytecodes,
...@@ -92,8 +88,10 @@ export function TickProcessor( ...@@ -92,8 +88,10 @@ export function TickProcessor(
onlySummary, onlySummary,
runtimeTimerFilter, runtimeTimerFilter,
preprocessJson) { preprocessJson) {
this.preprocessJson = preprocessJson; super({},
LogReader.call(this, { timedRange,
pairwiseTimedRange);
this.dispatchTable_ = {
'shared-library': { parsers: [parseString, parseInt, parseInt, parseInt], 'shared-library': { parsers: [parseString, parseInt, parseInt, parseInt],
processor: this.processSharedLibrary }, processor: this.processSharedLibrary },
'code-creation': { 'code-creation': {
...@@ -142,10 +140,10 @@ export function TickProcessor( ...@@ -142,10 +140,10 @@ export function TickProcessor(
// Obsolete row types. // Obsolete row types.
'code-allocate': null, 'code-allocate': null,
'begin-code-region': null, 'begin-code-region': null,
'end-code-region': null }, 'end-code-region': null
timedRange, };
pairwiseTimedRange);
this.preprocessJson = preprocessJson;
this.cppEntriesProvider_ = cppEntriesProvider; this.cppEntriesProvider_ = cppEntriesProvider;
this.callGraphSize_ = callGraphSize; this.callGraphSize_ = callGraphSize;
this.ignoreUnknown_ = ignoreUnknown; this.ignoreUnknown_ = ignoreUnknown;
...@@ -201,11 +199,10 @@ export function TickProcessor( ...@@ -201,11 +199,10 @@ export function TickProcessor(
this.generation_ = 1; this.generation_ = 1;
this.currentProducerProfile_ = null; this.currentProducerProfile_ = null;
this.onlySummary_ = onlySummary; this.onlySummary_ = onlySummary;
}; }
inherits(TickProcessor, LogReader);
TickProcessor.VmStates = { static VmStates = {
JS: 0, JS: 0,
GC: 1, GC: 1,
PARSER: 2, PARSER: 2,
...@@ -217,7 +214,7 @@ TickProcessor.VmStates = { ...@@ -217,7 +214,7 @@ TickProcessor.VmStates = {
}; };
TickProcessor.CodeTypes = { static CodeTypes = {
CPP: 0, CPP: 0,
SHARED_LIB: 1 SHARED_LIB: 1
}; };
...@@ -225,56 +222,56 @@ TickProcessor.CodeTypes = { ...@@ -225,56 +222,56 @@ TickProcessor.CodeTypes = {
// codeTypes_ map because there can be zillions of them. // codeTypes_ map because there can be zillions of them.
TickProcessor.CALL_PROFILE_CUTOFF_PCT = 1.0; static CALL_PROFILE_CUTOFF_PCT = 1.0;
TickProcessor.CALL_GRAPH_SIZE = 5; static CALL_GRAPH_SIZE = 5;
/** /**
* @override * @override
*/ */
TickProcessor.prototype.printError = function(str) { printError(str) {
printErr(str); printErr(str);
}; }
TickProcessor.prototype.setCodeType = function(name, type) { setCodeType(name, type) {
this.codeTypes_[name] = TickProcessor.CodeTypes[type]; this.codeTypes_[name] = TickProcessor.CodeTypes[type];
}; }
TickProcessor.prototype.isSharedLibrary = function(name) { isSharedLibrary(name) {
return this.codeTypes_[name] == TickProcessor.CodeTypes.SHARED_LIB; return this.codeTypes_[name] == TickProcessor.CodeTypes.SHARED_LIB;
}; }
TickProcessor.prototype.isCppCode = function(name) { isCppCode(name) {
return this.codeTypes_[name] == TickProcessor.CodeTypes.CPP; return this.codeTypes_[name] == TickProcessor.CodeTypes.CPP;
}; }
TickProcessor.prototype.isJsCode = function(name) { isJsCode(name) {
return name !== "UNKNOWN" && !(name in this.codeTypes_); return name !== "UNKNOWN" && !(name in this.codeTypes_);
}; }
TickProcessor.prototype.processLogFile = function(fileName) { processLogFile(fileName) {
this.lastLogFileName_ = fileName; this.lastLogFileName_ = fileName;
let line; let line;
while (line = readline()) { while (line = readline()) {
this.processLogLine(line); this.processLogLine(line);
} }
}; }
TickProcessor.prototype.processLogFileInTest = function(fileName) { processLogFileInTest(fileName) {
// Hack file name to avoid dealing with platform specifics. // Hack file name to avoid dealing with platform specifics.
this.lastLogFileName_ = 'v8.log'; this.lastLogFileName_ = 'v8.log';
const contents = readFile(fileName); const contents = readFile(fileName);
this.processLogChunk(contents); this.processLogChunk(contents);
}; }
TickProcessor.prototype.processSharedLibrary = function( processSharedLibrary(
name, startAddr, endAddr, aslrSlide) { name, startAddr, endAddr, aslrSlide) {
const entry = this.profile_.addLibrary(name, startAddr, endAddr, aslrSlide); const entry = this.profile_.addLibrary(name, startAddr, endAddr, aslrSlide);
this.setCodeType(entry.getName(), 'SHARED_LIB'); this.setCodeType(entry.getName(), 'SHARED_LIB');
...@@ -285,10 +282,10 @@ TickProcessor.prototype.processSharedLibrary = function( ...@@ -285,10 +282,10 @@ TickProcessor.prototype.processSharedLibrary = function(
self.profile_.addStaticCode(fName, fStart, fEnd); self.profile_.addStaticCode(fName, fStart, fEnd);
self.setCodeType(fName, 'CPP'); self.setCodeType(fName, 'CPP');
}); });
}; }
TickProcessor.prototype.processCodeCreation = function( processCodeCreation(
type, kind, timestamp, start, size, name, maybe_func) { type, kind, timestamp, start, size, name, maybe_func) {
if (maybe_func.length) { if (maybe_func.length) {
const funcAddr = parseInt(maybe_func[0]); const funcAddr = parseInt(maybe_func[0]);
...@@ -297,55 +294,55 @@ TickProcessor.prototype.processCodeCreation = function( ...@@ -297,55 +294,55 @@ TickProcessor.prototype.processCodeCreation = function(
} else { } else {
this.profile_.addCode(type, name, timestamp, start, size); this.profile_.addCode(type, name, timestamp, start, size);
} }
}; }
TickProcessor.prototype.processCodeDeopt = function( processCodeDeopt(
timestamp, size, code, inliningId, scriptOffset, bailoutType, timestamp, size, code, inliningId, scriptOffset, bailoutType,
sourcePositionText, deoptReasonText) { sourcePositionText, deoptReasonText) {
this.profile_.deoptCode(timestamp, code, inliningId, scriptOffset, this.profile_.deoptCode(timestamp, code, inliningId, scriptOffset,
bailoutType, sourcePositionText, deoptReasonText); bailoutType, sourcePositionText, deoptReasonText);
}; }
TickProcessor.prototype.processCodeMove = function(from, to) { processCodeMove(from, to) {
this.profile_.moveCode(from, to); this.profile_.moveCode(from, to);
}; }
TickProcessor.prototype.processCodeDelete = function(start) { processCodeDelete(start) {
this.profile_.deleteCode(start); this.profile_.deleteCode(start);
}; }
TickProcessor.prototype.processCodeSourceInfo = function( processCodeSourceInfo(
start, script, startPos, endPos, sourcePositions, inliningPositions, start, script, startPos, endPos, sourcePositions, inliningPositions,
inlinedFunctions) { inlinedFunctions) {
this.profile_.addSourcePositions(start, script, startPos, this.profile_.addSourcePositions(start, script, startPos,
endPos, sourcePositions, inliningPositions, inlinedFunctions); endPos, sourcePositions, inliningPositions, inlinedFunctions);
}; }
TickProcessor.prototype.processScriptSource = function(script, url, source) { processScriptSource(script, url, source) {
this.profile_.addScriptSource(script, url, source); this.profile_.addScriptSource(script, url, source);
}; }
TickProcessor.prototype.processFunctionMove = function(from, to) { processFunctionMove(from, to) {
this.profile_.moveFunc(from, to); this.profile_.moveFunc(from, to);
}; }
TickProcessor.prototype.includeTick = function(vmState) { includeTick(vmState) {
if (this.stateFilter_ !== null) { if (this.stateFilter_ !== null) {
return this.stateFilter_ == vmState; return this.stateFilter_ == vmState;
} else if (this.runtimeTimerFilter_ !== null) { } else if (this.runtimeTimerFilter_ !== null) {
return this.currentRuntimeTimer == this.runtimeTimerFilter_; return this.currentRuntimeTimer == this.runtimeTimerFilter_;
} }
return true; return true;
}; }
TickProcessor.prototype.processRuntimeTimerEvent = function(name) { processRuntimeTimerEvent(name) {
this.currentRuntimeTimer = name; this.currentRuntimeTimer = name;
} }
TickProcessor.prototype.processTick = function(pc, processTick(pc,
ns_since_start, ns_since_start,
is_external_callback, is_external_callback,
tos_or_external_callback, tos_or_external_callback,
...@@ -381,21 +378,21 @@ TickProcessor.prototype.processTick = function(pc, ...@@ -381,21 +378,21 @@ TickProcessor.prototype.processTick = function(pc,
this.profile_.recordTick( this.profile_.recordTick(
ns_since_start, vmState, ns_since_start, vmState,
this.processStack(pc, tos_or_external_callback, stack)); this.processStack(pc, tos_or_external_callback, stack));
}; }
TickProcessor.prototype.advanceDistortion = function() { advanceDistortion() {
this.distortion += this.distortion_per_entry; this.distortion += this.distortion_per_entry;
} }
TickProcessor.prototype.processHeapSampleBegin = function(space, state, ticks) { processHeapSampleBegin(space, state, ticks) {
if (space != 'Heap') return; if (space != 'Heap') return;
this.currentProducerProfile_ = new CallTree(); this.currentProducerProfile_ = new CallTree();
}; }
TickProcessor.prototype.processHeapSampleEnd = function(space, state) { processHeapSampleEnd(space, state) {
if (space != 'Heap' || !this.currentProducerProfile_) return; if (space != 'Heap' || !this.currentProducerProfile_) return;
print(`Generation ${this.generation_}:`); print(`Generation ${this.generation_}:`);
...@@ -410,10 +407,10 @@ TickProcessor.prototype.processHeapSampleEnd = function(space, state) { ...@@ -410,10 +407,10 @@ TickProcessor.prototype.processHeapSampleEnd = function(space, state) {
this.currentProducerProfile_ = null; this.currentProducerProfile_ = null;
this.generation_++; this.generation_++;
}; }
TickProcessor.prototype.printStatistics = function() { printStatistics() {
if (this.preprocessJson) { if (this.preprocessJson) {
this.profile_.writeJson(); this.profile_.writeJson();
return; return;
...@@ -492,29 +489,16 @@ TickProcessor.prototype.printStatistics = function() { ...@@ -492,29 +489,16 @@ TickProcessor.prototype.printStatistics = function() {
(rec2.internalFuncName < rec1.internalFuncName ? -1 : 1) ); (rec2.internalFuncName < rec1.internalFuncName ? -1 : 1) );
this.printHeavyProfile(heavyView.head.children); this.printHeavyProfile(heavyView.head.children);
} }
}; }
function padLeft(s, len) {
s = s.toString();
if (s.length < len) {
const padLength = len - s.length;
if (!(padLength in padLeft)) {
padLeft[padLength] = new Array(padLength + 1).join(' ');
}
s = padLeft[padLength] + s;
}
return s;
};
TickProcessor.prototype.printHeader = function(headerTitle) { printHeader(headerTitle) {
print(`\n [${headerTitle}]:`); print(`\n [${headerTitle}]:`);
print(' ticks total nonlib name'); print(' ticks total nonlib name');
}; }
TickProcessor.prototype.printLine = function( printLine(
entry, ticks, totalTicks, nonLibTicks) { entry, ticks, totalTicks, nonLibTicks) {
const pct = ticks * 100 / totalTicks; const pct = ticks * 100 / totalTicks;
const nonLibPct = nonLibTicks != null const nonLibPct = nonLibTicks != null
...@@ -526,7 +510,7 @@ TickProcessor.prototype.printLine = function( ...@@ -526,7 +510,7 @@ TickProcessor.prototype.printLine = function(
entry); entry);
} }
TickProcessor.prototype.printHeavyProfHeader = function() { printHeavyProfHeader() {
print('\n [Bottom up (heavy) profile]:'); print('\n [Bottom up (heavy) profile]:');
print(' Note: percentage shows a share of a particular caller in the ' + print(' Note: percentage shows a share of a particular caller in the ' +
'total\n' + 'total\n' +
...@@ -535,10 +519,10 @@ TickProcessor.prototype.printHeavyProfHeader = function() { ...@@ -535,10 +519,10 @@ TickProcessor.prototype.printHeavyProfHeader = function() {
TickProcessor.CALL_PROFILE_CUTOFF_PCT.toFixed(1) + TickProcessor.CALL_PROFILE_CUTOFF_PCT.toFixed(1) +
'% are not shown.\n'); '% are not shown.\n');
print(' ticks parent name'); print(' ticks parent name');
}; }
TickProcessor.prototype.processProfile = function( processProfile(
profile, filterP, func) { profile, filterP, func) {
for (let i = 0, n = profile.length; i < n; ++i) { for (let i = 0, n = profile.length; i < n; ++i) {
const rec = profile[i]; const rec = profile[i];
...@@ -549,7 +533,7 @@ TickProcessor.prototype.processProfile = function( ...@@ -549,7 +533,7 @@ TickProcessor.prototype.processProfile = function(
} }
}; };
TickProcessor.prototype.getLineAndColumn = function(name) { getLineAndColumn(name) {
const re = /:([0-9]+):([0-9]+)$/; const re = /:([0-9]+):([0-9]+)$/;
const array = re.exec(name); const array = re.exec(name);
if (!array) { if (!array) {
...@@ -558,12 +542,12 @@ TickProcessor.prototype.getLineAndColumn = function(name) { ...@@ -558,12 +542,12 @@ TickProcessor.prototype.getLineAndColumn = function(name) {
return {line: array[1], column: array[2]}; return {line: array[1], column: array[2]};
} }
TickProcessor.prototype.hasSourceMap = function() { hasSourceMap() {
return this.sourceMap != null; return this.sourceMap != null;
}; }
TickProcessor.prototype.formatFunctionName = function(funcName) { formatFunctionName(funcName) {
if (!this.hasSourceMap()) { if (!this.hasSourceMap()) {
return funcName; return funcName;
} }
...@@ -580,9 +564,9 @@ TickProcessor.prototype.formatFunctionName = function(funcName) { ...@@ -580,9 +564,9 @@ TickProcessor.prototype.formatFunctionName = function(funcName) {
const sourceColumn = entry[4] + 1; const sourceColumn = entry[4] + 1;
return sourceFile + ':' + sourceLine + ':' + sourceColumn + ' -> ' + funcName; return sourceFile + ':' + sourceLine + ':' + sourceColumn + ' -> ' + funcName;
}; }
TickProcessor.prototype.printEntries = function( printEntries(
profile, totalTicks, nonLibTicks, filterP, callback, printAllTicks) { profile, totalTicks, nonLibTicks, filterP, callback, printAllTicks) {
const that = this; const that = this;
this.processProfile(profile, filterP, function (rec) { this.processProfile(profile, filterP, function (rec) {
...@@ -593,10 +577,9 @@ TickProcessor.prototype.printEntries = function( ...@@ -593,10 +577,9 @@ TickProcessor.prototype.printEntries = function(
that.printLine(funcName, rec.selfTime, totalTicks, nonLibTicks); that.printLine(funcName, rec.selfTime, totalTicks, nonLibTicks);
} }
}); });
}; }
TickProcessor.prototype.printHeavyProfile = function(profile, opt_indent) { printHeavyProfile(profile, opt_indent) {
const self = this; const self = this;
const indent = opt_indent || 0; const indent = opt_indent || 0;
const indentStr = padLeft('', indent); const indentStr = padLeft('', indent);
...@@ -616,14 +599,27 @@ TickProcessor.prototype.printHeavyProfile = function(profile, opt_indent) { ...@@ -616,14 +599,27 @@ TickProcessor.prototype.printHeavyProfile = function(profile, opt_indent) {
print(''); print('');
} }
}); });
}; }
}
function CppEntriesProvider() { function padLeft(s, len) {
s = s.toString();
if (s.length < len) {
const padLength = len - s.length;
if (!(padLength in padLeft)) {
padLeft[padLength] = new Array(padLength + 1).join(' ');
}
s = padLeft[padLength] + s;
}
return s;
}; };
CppEntriesProvider.prototype.parseVmSymbols = function( class CppEntriesProvider {
parseVmSymbols(
libName, libStart, libEnd, libASLRSlide, processorFunc) { libName, libStart, libEnd, libASLRSlide, processorFunc) {
this.loadSymbols(libName); this.loadSymbols(libName);
...@@ -686,17 +682,20 @@ CppEntriesProvider.prototype.parseVmSymbols = function( ...@@ -686,17 +682,20 @@ CppEntriesProvider.prototype.parseVmSymbols = function(
addEntry(funcInfo); addEntry(funcInfo);
} }
addEntry({name: '', start: libEnd}); addEntry({name: '', start: libEnd});
}; }
CppEntriesProvider.prototype.loadSymbols = function(libName) { loadSymbols(libName) {
}; }
parseNextLine() { return false }
CppEntriesProvider.prototype.parseNextLine = () => false; }
export function UnixCppEntriesProvider(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary) { export class UnixCppEntriesProvider extends CppEntriesProvider {
constructor(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary) {
super();
this.symbols = []; this.symbols = [];
// File offset of a symbol minus the virtual address of a symbol found in // File offset of a symbol minus the virtual address of a symbol found in
// the symbol table. // the symbol table.
...@@ -707,11 +706,10 @@ export function UnixCppEntriesProvider(nmExec, objdumpExec, targetRootFS, apkEmb ...@@ -707,11 +706,10 @@ export function UnixCppEntriesProvider(nmExec, objdumpExec, targetRootFS, apkEmb
this.targetRootFS = targetRootFS; this.targetRootFS = targetRootFS;
this.apkEmbeddedLibrary = apkEmbeddedLibrary; this.apkEmbeddedLibrary = apkEmbeddedLibrary;
this.FUNC_RE = /^([0-9a-fA-F]{8,16}) ([0-9a-fA-F]{8,16} )?[tTwW] (.*)$/; this.FUNC_RE = /^([0-9a-fA-F]{8,16}) ([0-9a-fA-F]{8,16} )?[tTwW] (.*)$/;
}; }
inherits(UnixCppEntriesProvider, CppEntriesProvider);
UnixCppEntriesProvider.prototype.loadSymbols = function(libName) { loadSymbols(libName) {
this.parsePos = 0; this.parsePos = 0;
if (this.apkEmbeddedLibrary && libName.endsWith('.apk')) { if (this.apkEmbeddedLibrary && libName.endsWith('.apk')) {
libName = this.apkEmbeddedLibrary; libName = this.apkEmbeddedLibrary;
...@@ -737,10 +735,10 @@ UnixCppEntriesProvider.prototype.loadSymbols = function(libName) { ...@@ -737,10 +735,10 @@ UnixCppEntriesProvider.prototype.loadSymbols = function(libName) {
// If the library cannot be found on this system let's not panic. // If the library cannot be found on this system let's not panic.
this.symbols = ['', '']; this.symbols = ['', ''];
} }
}; }
UnixCppEntriesProvider.prototype.parseNextLine = function() { parseNextLine() {
if (this.symbols.length == 0) { if (this.symbols.length == 0) {
return false; return false;
} }
...@@ -762,18 +760,18 @@ UnixCppEntriesProvider.prototype.parseNextLine = function() { ...@@ -762,18 +760,18 @@ UnixCppEntriesProvider.prototype.parseNextLine = function() {
} }
} }
return funcInfo; return funcInfo;
}; }
}
export function MacCppEntriesProvider(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary) { export class MacCppEntriesProvider extends UnixCppEntriesProvider {
UnixCppEntriesProvider.call(this, nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary); constructor(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary) {
super(nmExec, objdumpExec, targetRootFS, apkEmbeddedLibrary);
// Note an empty group. It is required, as UnixCppEntriesProvider expects 3 groups. // Note an empty group. It is required, as UnixCppEntriesProvider expects 3 groups.
this.FUNC_RE = /^([0-9a-fA-F]{8,16})() (.*)$/; this.FUNC_RE = /^([0-9a-fA-F]{8,16})() (.*)$/;
}; }
inherits(MacCppEntriesProvider, UnixCppEntriesProvider);
MacCppEntriesProvider.prototype.loadSymbols = function(libName) { loadSymbols(libName) {
this.parsePos = 0; this.parsePos = 0;
libName = this.targetRootFS + libName; libName = this.targetRootFS + libName;
...@@ -785,34 +783,36 @@ MacCppEntriesProvider.prototype.loadSymbols = function(libName) { ...@@ -785,34 +783,36 @@ MacCppEntriesProvider.prototype.loadSymbols = function(libName) {
// If the library cannot be found on this system let's not panic. // If the library cannot be found on this system let's not panic.
this.symbols = ''; this.symbols = '';
} }
}; }
}
export function WindowsCppEntriesProvider(_ignored_nmExec, _ignored_objdumpExec, targetRootFS, export class WindowsCppEntriesProvider extends CppEntriesProvider {
constructor(_ignored_nmExec, _ignored_objdumpExec, targetRootFS,
_ignored_apkEmbeddedLibrary) { _ignored_apkEmbeddedLibrary) {
super();
this.targetRootFS = targetRootFS; this.targetRootFS = targetRootFS;
this.symbols = ''; this.symbols = '';
this.parsePos = 0; this.parsePos = 0;
}; };
inherits(WindowsCppEntriesProvider, CppEntriesProvider);
WindowsCppEntriesProvider.FILENAME_RE = /^(.*)\.([^.]+)$/; static FILENAME_RE = /^(.*)\.([^.]+)$/;
WindowsCppEntriesProvider.FUNC_RE = static FUNC_RE =
/^\s+0001:[0-9a-fA-F]{8}\s+([_\?@$0-9a-zA-Z]+)\s+([0-9a-fA-F]{8}).*$/; /^\s+0001:[0-9a-fA-F]{8}\s+([_\?@$0-9a-zA-Z]+)\s+([0-9a-fA-F]{8}).*$/;
WindowsCppEntriesProvider.IMAGE_BASE_RE = static IMAGE_BASE_RE =
/^\s+0000:00000000\s+___ImageBase\s+([0-9a-fA-F]{8}).*$/; /^\s+0000:00000000\s+___ImageBase\s+([0-9a-fA-F]{8}).*$/;
// This is almost a constant on Windows. // This is almost a constant on Windows.
WindowsCppEntriesProvider.EXE_IMAGE_BASE = 0x00400000; static EXE_IMAGE_BASE = 0x00400000;
WindowsCppEntriesProvider.prototype.loadSymbols = function(libName) { loadSymbols(libName) {
libName = this.targetRootFS + libName; libName = this.targetRootFS + libName;
const fileNameFields = libName.match(WindowsCppEntriesProvider.FILENAME_RE); const fileNameFields = libName.match(WindowsCppEntriesProvider.FILENAME_RE);
if (!fileNameFields) return; if (!fileNameFields) return;
...@@ -827,7 +827,7 @@ WindowsCppEntriesProvider.prototype.loadSymbols = function(libName) { ...@@ -827,7 +827,7 @@ WindowsCppEntriesProvider.prototype.loadSymbols = function(libName) {
}; };
WindowsCppEntriesProvider.prototype.parseNextLine = function() { parseNextLine() {
const lineEndPos = this.symbols.indexOf('\r\n', this.parsePos); const lineEndPos = this.symbols.indexOf('\r\n', this.parsePos);
if (lineEndPos == -1) { if (lineEndPos == -1) {
return false; return false;
...@@ -862,14 +862,15 @@ WindowsCppEntriesProvider.prototype.parseNextLine = function() { ...@@ -862,14 +862,15 @@ WindowsCppEntriesProvider.prototype.parseNextLine = function() {
* *
* ?LookupInDescriptor@JSObject@internal@v8@@...arguments info... * ?LookupInDescriptor@JSObject@internal@v8@@...arguments info...
*/ */
WindowsCppEntriesProvider.prototype.unmangleName = function(name) { unmangleName(name) {
// Empty or non-mangled name. // Empty or non-mangled name.
if (name.length < 1 || name.charAt(0) != '?') return name; if (name.length < 1 || name.charAt(0) != '?') return name;
const nameEndPos = name.indexOf('@@'); const nameEndPos = name.indexOf('@@');
const components = name.substring(1, nameEndPos).split('@'); const components = name.substring(1, nameEndPos).split('@');
components.reverse(); components.reverse();
return components.join('::'); return components.join('::');
}; }
}
export class ArgumentsProcessor extends BaseArgumentsProcessor { export class ArgumentsProcessor extends BaseArgumentsProcessor {
......
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