Don't keep data about JS code that is never executed.

This reduces memory usage of tickprocessor. Thanks to William Hesse for pointing out this issue.

Also speed up static symbols loading.

Review URL: http://codereview.chromium.org/113101

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1902 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ebdf1d1e
...@@ -123,4 +123,36 @@ function assertNoEntry(codeMap, addr) { ...@@ -123,4 +123,36 @@ function assertNoEntry(codeMap, addr) {
codeMap.addCode(0x1700, newCodeEntry(0x100, 'code')); codeMap.addCode(0x1700, newCodeEntry(0x100, 'code'));
assertEntry(codeMap, 'code', 0x1500); assertEntry(codeMap, 'code', 0x1500);
assertEntry(codeMap, 'code {1}', 0x1700); assertEntry(codeMap, 'code {1}', 0x1700);
// Test name stability.
assertEntry(codeMap, 'code', 0x1500);
assertEntry(codeMap, 'code {1}', 0x1700);
})();
(function testStaticEntriesExport() {
var codeMap = new devtools.profiler.CodeMap();
codeMap.addStaticCode(0x1500, newCodeEntry(0x3000, 'lib1'));
codeMap.addStaticCode(0x15500, newCodeEntry(0x5000, 'lib2'));
codeMap.addStaticCode(0x155500, newCodeEntry(0x10000, 'lib3'));
var allStatics = codeMap.getAllStaticEntries();
allStatics.sort();
assertEquals(['lib1: 3000', 'lib2: 5000', 'lib3: 10000'], allStatics);
})();
(function testDynamicEntriesExport() {
var codeMap = new devtools.profiler.CodeMap();
codeMap.addCode(0x1500, newCodeEntry(0x200, 'code1'));
codeMap.addCode(0x1700, newCodeEntry(0x100, 'code2'));
codeMap.addCode(0x1900, newCodeEntry(0x50, 'code3'));
var allDynamics = codeMap.getAllDynamicEntries();
allDynamics.sort();
assertEquals(['code1: 200', 'code2: 100', 'code3: 50'], allDynamics);
codeMap.deleteCode(0x1700);
var allDynamics2 = codeMap.getAllDynamicEntries();
allDynamics2.sort();
assertEquals(['code1: 200', 'code3: 50'], allDynamics2);
codeMap.deleteCode(0x1500);
var allDynamics3 = codeMap.getAllDynamicEntries();
assertEquals(['code3: 50'], allDynamics3);
})(); })();
...@@ -43,10 +43,8 @@ devtools.profiler.CodeMap = function() { ...@@ -43,10 +43,8 @@ devtools.profiler.CodeMap = function() {
this.dynamics_ = new goog.structs.SplayTree(); this.dynamics_ = new goog.structs.SplayTree();
/** /**
* Deleted code entries. Used for code collected by the GC. * Name generator for entries having duplicate names.
*/ */
this.deleted_ = [];
this.dynamicsNameGen_ = new devtools.profiler.CodeMap.NameGenerator(); this.dynamicsNameGen_ = new devtools.profiler.CodeMap.NameGenerator();
/** /**
...@@ -81,8 +79,6 @@ devtools.profiler.CodeMap.PAGE_SIZE = ...@@ -81,8 +79,6 @@ devtools.profiler.CodeMap.PAGE_SIZE =
* @param {devtools.profiler.CodeMap.CodeEntry} codeEntry Code entry object. * @param {devtools.profiler.CodeMap.CodeEntry} codeEntry Code entry object.
*/ */
devtools.profiler.CodeMap.prototype.addCode = function(start, codeEntry) { devtools.profiler.CodeMap.prototype.addCode = function(start, codeEntry) {
var entryName = this.dynamicsNameGen_.getName(codeEntry.name);
codeEntry.name = entryName;
this.dynamics_.insert(start, codeEntry); this.dynamics_.insert(start, codeEntry);
}; };
...@@ -102,14 +98,12 @@ devtools.profiler.CodeMap.prototype.moveCode = function(from, to) { ...@@ -102,14 +98,12 @@ devtools.profiler.CodeMap.prototype.moveCode = function(from, to) {
/** /**
* Discards a dynamic code entry. Throws an exception if there is no dynamic * Discards a dynamic code entry. Throws an exception if there is no dynamic
* code entry with the specified starting address. The entry will still be * code entry with the specified starting address.
* returned from the 'getAllDynamicEntries' method.
* *
* @param {number} start The starting address of the entry being deleted. * @param {number} start The starting address of the entry being deleted.
*/ */
devtools.profiler.CodeMap.prototype.deleteCode = function(start) { devtools.profiler.CodeMap.prototype.deleteCode = function(start) {
var removedNode = this.dynamics_.remove(start); var removedNode = this.dynamics_.remove(start);
this.deleted_.push(removedNode.value);
}; };
...@@ -168,7 +162,14 @@ devtools.profiler.CodeMap.prototype.findEntry = function(addr) { ...@@ -168,7 +162,14 @@ devtools.profiler.CodeMap.prototype.findEntry = function(addr) {
var min = this.dynamics_.findMin(); var min = this.dynamics_.findMin();
var max = this.dynamics_.findMax(); var max = this.dynamics_.findMax();
if (max != null && addr < (max.key + max.value.size) && addr >= min.key) { if (max != null && addr < (max.key + max.value.size) && addr >= min.key) {
return this.findInTree_(this.dynamics_, addr); var dynaEntry = this.findInTree_(this.dynamics_, addr);
if (dynaEntry == null) return null;
// Dedupe entry name.
if (!dynaEntry.nameUpdated_) {
dynaEntry.name = this.dynamicsNameGen_.getName(dynaEntry.name);
dynaEntry.nameUpdated_ = true;
}
return dynaEntry;
} }
return null; return null;
}; };
...@@ -178,8 +179,7 @@ devtools.profiler.CodeMap.prototype.findEntry = function(addr) { ...@@ -178,8 +179,7 @@ devtools.profiler.CodeMap.prototype.findEntry = function(addr) {
* Returns an array of all dynamic code entries, including deleted ones. * Returns an array of all dynamic code entries, including deleted ones.
*/ */
devtools.profiler.CodeMap.prototype.getAllDynamicEntries = function() { devtools.profiler.CodeMap.prototype.getAllDynamicEntries = function() {
var dynamicEntries = this.dynamics_.exportValues(); return this.dynamics_.exportValues();
return dynamicEntries.concat(this.deleted_);
}; };
...@@ -201,6 +201,7 @@ devtools.profiler.CodeMap.prototype.getAllStaticEntries = function() { ...@@ -201,6 +201,7 @@ devtools.profiler.CodeMap.prototype.getAllStaticEntries = function() {
devtools.profiler.CodeMap.CodeEntry = function(size, opt_name) { devtools.profiler.CodeMap.CodeEntry = function(size, opt_name) {
this.size = size; this.size = size;
this.name = opt_name || ''; this.name = opt_name || '';
this.nameUpdated_ = false;
}; };
......
...@@ -99,10 +99,11 @@ TickProcessor.VmStates = { ...@@ -99,10 +99,11 @@ TickProcessor.VmStates = {
TickProcessor.CodeTypes = { TickProcessor.CodeTypes = {
JS: 0, CPP: 0,
CPP: 1, SHARED_LIB: 1
SHARED_LIB: 2
}; };
// Otherwise, this is JS-related code. We are not adding it to
// codeTypes_ map because there can be zillions of them.
TickProcessor.RecordsDispatch = { TickProcessor.RecordsDispatch = {
...@@ -142,7 +143,7 @@ TickProcessor.prototype.isCppCode = function(name) { ...@@ -142,7 +143,7 @@ TickProcessor.prototype.isCppCode = function(name) {
TickProcessor.prototype.isJsCode = function(name) { TickProcessor.prototype.isJsCode = function(name) {
return this.codeTypes_[name] == TickProcessor.CodeTypes.JS; return !(name in this.codeTypes_);
}; };
...@@ -220,7 +221,6 @@ TickProcessor.prototype.processSharedLibrary = function( ...@@ -220,7 +221,6 @@ TickProcessor.prototype.processSharedLibrary = function(
TickProcessor.prototype.processCodeCreation = function( TickProcessor.prototype.processCodeCreation = function(
type, start, size, name) { type, start, size, name) {
var entry = this.profile_.addCode(type, name, start, size); var entry = this.profile_.addCode(type, name, start, size);
this.setCodeType(entry.getName(), 'JS');
}; };
...@@ -415,8 +415,7 @@ function CppEntriesProvider() { ...@@ -415,8 +415,7 @@ function CppEntriesProvider() {
CppEntriesProvider.prototype.parseVmSymbols = function( CppEntriesProvider.prototype.parseVmSymbols = function(
libName, libStart, libEnd, processorFunc) { libName, libStart, libEnd, processorFunc) {
var syms = this.loadSymbols(libName); this.loadSymbols(libName);
if (syms.length == 0) return;
var prevEntry; var prevEntry;
...@@ -428,11 +427,12 @@ CppEntriesProvider.prototype.parseVmSymbols = function( ...@@ -428,11 +427,12 @@ CppEntriesProvider.prototype.parseVmSymbols = function(
} }
} }
for (var i = 0, n = syms.length; i < n; ++i) { while (true) {
var line = syms[i]; var funcInfo = this.parseNextLine();
var funcInfo = this.parseLine(line); if (funcInfo === null) {
if (!funcInfo) {
continue; continue;
} else if (funcInfo === false) {
break;
} }
if (funcInfo.start < libStart && funcInfo.start < libEnd - libStart) { if (funcInfo.start < libStart && funcInfo.start < libEnd - libStart) {
funcInfo.start += libStart; funcInfo.start += libStart;
...@@ -445,12 +445,11 @@ CppEntriesProvider.prototype.parseVmSymbols = function( ...@@ -445,12 +445,11 @@ CppEntriesProvider.prototype.parseVmSymbols = function(
CppEntriesProvider.prototype.loadSymbols = function(libName) { CppEntriesProvider.prototype.loadSymbols = function(libName) {
return [];
}; };
CppEntriesProvider.prototype.parseLine = function(line) { CppEntriesProvider.prototype.parseNextLine = function() {
return { name: '', start: 0 }; return false;
}; };
...@@ -462,6 +461,8 @@ function inherits(childCtor, parentCtor) { ...@@ -462,6 +461,8 @@ function inherits(childCtor, parentCtor) {
function UnixCppEntriesProvider() { function UnixCppEntriesProvider() {
this.symbols = [];
this.parsePos = 0;
}; };
inherits(UnixCppEntriesProvider, CppEntriesProvider); inherits(UnixCppEntriesProvider, CppEntriesProvider);
...@@ -470,20 +471,35 @@ UnixCppEntriesProvider.FUNC_RE = /^([0-9a-fA-F]{8}) . (.*)$/; ...@@ -470,20 +471,35 @@ UnixCppEntriesProvider.FUNC_RE = /^([0-9a-fA-F]{8}) . (.*)$/;
UnixCppEntriesProvider.prototype.loadSymbols = function(libName) { UnixCppEntriesProvider.prototype.loadSymbols = function(libName) {
var normalSyms = os.system('nm', ['-C', '-n', libName], -1, -1); this.symbols = [
var dynaSyms = os.system('nm', ['-C', '-n', '-D', libName], -1, -1); os.system('nm', ['-C', '-n', libName], -1, -1),
var syms = (normalSyms + dynaSyms).split('\n'); os.system('nm', ['-C', '-n', '-D', libName], -1, -1)
return syms; ];
this.parsePos = 0;
}; };
UnixCppEntriesProvider.prototype.parseLine = function(line) { UnixCppEntriesProvider.prototype.parseNextLine = function() {
if (this.symbols.length == 0) {
return false;
}
var lineEndPos = this.symbols[0].indexOf('\n', this.parsePos);
if (lineEndPos == -1) {
this.symbols.shift();
this.parsePos = 0;
return this.parseNextLine();
}
var line = this.symbols[0].substring(this.parsePos, lineEndPos);
this.parsePos = lineEndPos + 1;
var fields = line.match(UnixCppEntriesProvider.FUNC_RE); var fields = line.match(UnixCppEntriesProvider.FUNC_RE);
return fields ? { name: fields[2], start: parseInt(fields[1], 16) } : null; return fields ? { name: fields[2], start: parseInt(fields[1], 16) } : null;
}; };
function WindowsCppEntriesProvider() { function WindowsCppEntriesProvider() {
this.symbols = '';
this.parsePos = 0;
}; };
inherits(WindowsCppEntriesProvider, CppEntriesProvider); inherits(WindowsCppEntriesProvider, CppEntriesProvider);
...@@ -498,13 +514,20 @@ WindowsCppEntriesProvider.FUNC_RE = ...@@ -498,13 +514,20 @@ WindowsCppEntriesProvider.FUNC_RE =
WindowsCppEntriesProvider.prototype.loadSymbols = function(libName) { WindowsCppEntriesProvider.prototype.loadSymbols = function(libName) {
var fileNameFields = libName.match(WindowsCppEntriesProvider.FILENAME_RE); var fileNameFields = libName.match(WindowsCppEntriesProvider.FILENAME_RE);
// Only try to load symbols for the .exe file. // Only try to load symbols for the .exe file.
if (!fileNameFields) return []; if (!fileNameFields) return;
var mapFileName = fileNameFields[1] + '.map'; var mapFileName = fileNameFields[1] + '.map';
return readFile(mapFileName).split('\r\n'); this.symbols = readFile(mapFileName);
}; };
WindowsCppEntriesProvider.prototype.parseLine = function(line) { WindowsCppEntriesProvider.prototype.parseNextLine = function() {
var lineEndPos = this.symbols.indexOf('\r\n', this.parsePos);
if (lineEndPos == -1) {
return false;
}
var line = this.symbols.substring(this.parsePos, lineEndPos);
this.parsePos = lineEndPos + 2;
var fields = line.match(WindowsCppEntriesProvider.FUNC_RE); var fields = line.match(WindowsCppEntriesProvider.FUNC_RE);
return fields ? return fields ?
{ name: this.unmangleName(fields[1]), start: parseInt(fields[2], 16) } : { name: this.unmangleName(fields[1]), start: parseInt(fields[2], 16) } :
......
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