| Index: tools/profile.js
|
| diff --git a/tools/profile.js b/tools/profile.js
|
| index f0814a2f0d9cc3303cf5ae8f5633058a1e7243cd..7d189e056717e4a43b6a09f4c8cab6d1704d675f 100644
|
| --- a/tools/profile.js
|
| +++ b/tools/profile.js
|
| @@ -37,6 +37,7 @@ function Profile() {
|
| this.topDownTree_ = new CallTree();
|
| this.bottomUpTree_ = new CallTree();
|
| this.c_entries_ = {};
|
| + this.ticks_ = [];
|
| };
|
|
|
|
|
| @@ -235,7 +236,7 @@ Profile.prototype.findEntry = function(addr) {
|
| *
|
| * @param {Array<number>} stack Stack sample.
|
| */
|
| -Profile.prototype.recordTick = function(stack) {
|
| +Profile.prototype.recordTick = function(time_ns, vmState, stack) {
|
| var processedStack = this.resolveAndFilterFuncs_(stack);
|
| this.bottomUpTree_.addPath(processedStack);
|
| processedStack.reverse();
|
| @@ -832,3 +833,146 @@ CallTree.Node.prototype.descendToChild = function(
|
| }
|
| return curr;
|
| };
|
| +
|
| +function JsonProfile() {
|
| + this.codeMap_ = new CodeMap();
|
| + this.codeEntries_ = [];
|
| + this.functionEntries_ = [];
|
| + this.ticks_ = [];
|
| +}
|
| +
|
| +JsonProfile.prototype.addLibrary = function(
|
| + name, startAddr, endAddr) {
|
| + var entry = new CodeMap.CodeEntry(
|
| + endAddr - startAddr, name, 'SHARED_LIB');
|
| + this.codeMap_.addLibrary(startAddr, entry);
|
| +
|
| + entry.codeId = this.codeEntries_.length;
|
| + this.codeEntries_.push({name : entry.name, type : entry.type});
|
| + return entry;
|
| +};
|
| +
|
| +JsonProfile.prototype.addStaticCode = function(
|
| + name, startAddr, endAddr) {
|
| + var entry = new CodeMap.CodeEntry(
|
| + endAddr - startAddr, name, 'CPP');
|
| + this.codeMap_.addStaticCode(startAddr, entry);
|
| +
|
| + entry.codeId = this.codeEntries_.length;
|
| + this.codeEntries_.push({name : entry.name, type : entry.type});
|
| + return entry;
|
| +};
|
| +
|
| +JsonProfile.prototype.addCode = function(
|
| + kind, name, start, size) {
|
| + var entry = new CodeMap.CodeEntry(size, name, 'CODE');
|
| + this.codeMap_.addCode(start, entry);
|
| +
|
| + entry.codeId = this.codeEntries_.length;
|
| + this.codeEntries_.push({name : entry.name, type : entry.type, kind : kind});
|
| +
|
| + return entry;
|
| +};
|
| +
|
| +JsonProfile.prototype.addFuncCode = function(
|
| + kind, name, start, size, funcAddr, state) {
|
| + // As code and functions are in the same address space,
|
| + // it is safe to put them in a single code map.
|
| + var func = this.codeMap_.findDynamicEntryByStartAddress(funcAddr);
|
| + if (!func) {
|
| + var func = new CodeMap.CodeEntry(0, name, 'SFI');
|
| + this.codeMap_.addCode(funcAddr, func);
|
| +
|
| + func.funcId = this.functionEntries_.length;
|
| + this.functionEntries_.push({name : name, codes : []});
|
| + } else if (func.name !== name) {
|
| + // Function object has been overwritten with a new one.
|
| + func.name = name;
|
| +
|
| + func.funcId = this.functionEntries_.length;
|
| + this.functionEntries_.push({name : name, codes : []});
|
| + }
|
| + // TODO(jarin): Insert the code object into the SFI's code list.
|
| + var entry = this.codeMap_.findDynamicEntryByStartAddress(start);
|
| + if (entry) {
|
| + // TODO(jarin) This does not look correct, we should really
|
| + // update the code object (remove the old one and insert this one).
|
| + if (entry.size === size && entry.func === func) {
|
| + // Entry state has changed.
|
| + entry.state = state;
|
| + }
|
| + } else {
|
| + var entry = new CodeMap.CodeEntry(size, name, 'JS');
|
| + this.codeMap_.addCode(start, entry);
|
| +
|
| + entry.codeId = this.codeEntries_.length;
|
| +
|
| + this.functionEntries_[func.funcId].codes.push(entry.codeId);
|
| +
|
| + if (state === 0) {
|
| + kind = "Builtin";
|
| + } else if (state === 1) {
|
| + kind = "Unopt";
|
| + } else if (state === 2) {
|
| + kind = "Opt";
|
| + }
|
| +
|
| + this.codeEntries_.push({
|
| + name : entry.name,
|
| + type : entry.type,
|
| + kind : kind,
|
| + func : func.funcId
|
| + });
|
| + }
|
| + return entry;
|
| +};
|
| +
|
| +JsonProfile.prototype.moveCode = function(from, to) {
|
| + try {
|
| + this.codeMap_.moveCode(from, to);
|
| + } catch (e) {
|
| + printErr("Move: unknown source " + from);
|
| + }
|
| +};
|
| +
|
| +JsonProfile.prototype.deleteCode = function(start) {
|
| + try {
|
| + this.codeMap_.deleteCode(start);
|
| + } catch (e) {
|
| + printErr("Delete: unknown address " + start);
|
| + }
|
| +};
|
| +
|
| +JsonProfile.prototype.moveFunc = function(from, to) {
|
| + if (this.codeMap_.findDynamicEntryByStartAddress(from)) {
|
| + this.codeMap_.moveCode(from, to);
|
| + }
|
| +};
|
| +
|
| +JsonProfile.prototype.findEntry = function(addr) {
|
| + return this.codeMap_.findEntry(addr);
|
| +};
|
| +
|
| +JsonProfile.prototype.recordTick = function(time_ns, vmState, stack) {
|
| + // TODO(jarin) Resolve the frame-less case (when top of stack is
|
| + // known code).
|
| + var processedStack = [];
|
| + for (var i = 0; i < stack.length; i++) {
|
| + var resolved = this.codeMap_.findAddress(stack[i]);
|
| + if (resolved) {
|
| + processedStack.push(resolved.entry.codeId, resolved.offset);
|
| + } else {
|
| + processedStack.push(-1, stack[i]);
|
| + }
|
| + }
|
| + this.ticks_.push({ tm : time_ns, vm : vmState, s : processedStack });
|
| +};
|
| +
|
| +JsonProfile.prototype.writeJson = function() {
|
| + var toplevel = {
|
| + code : this.codeEntries_,
|
| + functions : this.functionEntries_,
|
| + ticks : this.ticks_
|
| + };
|
| + write(JSON.stringify(toplevel));
|
| +};
|
|
|