Implemented processing of compressed log files.

- fixed address delta calculation;
- code creations are also compressed to be in sync with other events;
- factored out a base class from TickProcessor to reuse code in DevTools profiler.

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


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2216 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5f77401b
......@@ -261,14 +261,20 @@ void LogMessageBuilder::AppendAddress(Address addr) {
void LogMessageBuilder::AppendAddress(Address addr, Address bias) {
if (!FLAG_compress_log || bias == NULL) {
if (!FLAG_compress_log) {
Append("0x%" V8PRIxPTR, addr);
} else if (bias == NULL) {
Append("%" V8PRIxPTR, addr);
} else {
intptr_t delta = addr - bias;
// To avoid printing negative offsets in an unsigned form,
// we are printing an absolute value with a sign.
const char sign = delta >= 0 ? '+' : '-';
if (sign == '-') { delta = -delta; }
uintptr_t delta;
char sign;
if (addr >= bias) {
delta = addr - bias;
sign = '+';
} else {
delta = bias - addr;
sign = '-';
}
Append("%c%" V8PRIxPTR, sign, delta);
}
}
......
......@@ -627,6 +627,42 @@ void Logger::DeleteEvent(const char* name, void* object) {
}
#ifdef ENABLE_LOGGING_AND_PROFILING
// A class that contains all common code dealing with record compression.
class CompressionHelper {
public:
explicit CompressionHelper(int window_size)
: compressor_(window_size), repeat_count_(0) { }
// Handles storing message in compressor, retrieving the previous one and
// prefixing it with repeat count, if needed.
// Returns true if message needs to be written to log.
bool HandleMessage(LogMessageBuilder* msg) {
if (!msg->StoreInCompressor(&compressor_)) {
// Current message repeats the previous one, don't write it.
++repeat_count_;
return false;
}
if (repeat_count_ == 0) {
return msg->RetrieveCompressedPrevious(&compressor_);
}
OS::SNPrintF(prefix_, "%s,%d,",
Logger::log_events_[Logger::REPEAT_META_EVENT],
repeat_count_ + 1);
repeat_count_ = 0;
return msg->RetrieveCompressedPrevious(&compressor_, prefix_.start());
}
private:
LogRecordCompressor compressor_;
int repeat_count_;
EmbeddedVector<char, 20> prefix_;
};
#endif // ENABLE_LOGGING_AND_PROFILING
void Logger::CodeCreateEvent(LogEventsAndTags tag,
Code* code,
const char* comment) {
......@@ -643,6 +679,10 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
msg.Append(*p);
}
msg.Append('"');
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
if (!compression_helper_->HandleMessage(&msg)) return;
}
msg.Append('\n');
msg.WriteToLogFile();
#endif
......@@ -657,7 +697,12 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, String* name) {
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]);
msg.AppendAddress(code->address());
msg.Append(",%d,\"%s\"\n", code->ExecutableSize(), *str);
msg.Append(",%d,\"%s\"", code->ExecutableSize(), *str);
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
if (!compression_helper_->HandleMessage(&msg)) return;
}
msg.Append('\n');
msg.WriteToLogFile();
#endif
}
......@@ -675,8 +720,13 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag,
source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]);
msg.AppendAddress(code->address());
msg.Append(",%d,\"%s %s:%d\"\n",
msg.Append(",%d,\"%s %s:%d\"",
code->ExecutableSize(), *str, *sourcestr, line);
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
if (!compression_helper_->HandleMessage(&msg)) return;
}
msg.Append('\n');
msg.WriteToLogFile();
#endif
}
......@@ -688,7 +738,12 @@ void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) {
LogMessageBuilder msg;
msg.Append("%s,%s,", log_events_[CODE_CREATION_EVENT], log_events_[tag]);
msg.AppendAddress(code->address());
msg.Append(",%d,\"args_count: %d\"\n", code->ExecutableSize(), args_count);
msg.Append(",%d,\"args_count: %d\"", code->ExecutableSize(), args_count);
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
if (!compression_helper_->HandleMessage(&msg)) return;
}
msg.Append('\n');
msg.WriteToLogFile();
#endif
}
......@@ -703,48 +758,17 @@ void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
msg.AppendAddress(code->address());
msg.Append(",%d,\"", code->ExecutableSize());
msg.AppendDetailed(source, false);
msg.Append("\"\n");
msg.Append('\"');
if (FLAG_compress_log) {
ASSERT(compression_helper_ != NULL);
if (!compression_helper_->HandleMessage(&msg)) return;
}
msg.Append('\n');
msg.WriteToLogFile();
#endif
}
#ifdef ENABLE_LOGGING_AND_PROFILING
// A class that contains all common code dealing with record compression.
class CompressionHelper {
public:
explicit CompressionHelper(int window_size)
: compressor_(window_size), repeat_count_(0) { }
// Handles storing message in compressor, retrieving the previous one and
// prefixing it with repeat count, if needed.
// Returns true if message needs to be written to log.
bool HandleMessage(LogMessageBuilder* msg) {
if (!msg->StoreInCompressor(&compressor_)) {
// Current message repeats the previous one, don't write it.
++repeat_count_;
return false;
}
if (repeat_count_ == 0) {
return msg->RetrieveCompressedPrevious(&compressor_);
}
OS::SNPrintF(prefix_, "%s,%d,",
Logger::log_events_[Logger::REPEAT_META_EVENT],
repeat_count_ + 1);
repeat_count_ = 0;
return msg->RetrieveCompressedPrevious(&compressor_, prefix_.start());
}
private:
LogRecordCompressor compressor_;
int repeat_count_;
EmbeddedVector<char, 20> prefix_;
};
#endif // ENABLE_LOGGING_AND_PROFILING
void Logger::CodeMoveEvent(Address from, Address to) {
#ifdef ENABLE_LOGGING_AND_PROFILING
static Address prev_to_ = NULL;
......
// 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.
// Load CSV Parser and Log Reader implementations from <project root>/tools.
// Files: tools/csvparser.js tools/logreader.js
(function testAddressParser() {
var reader = new devtools.profiler.LogReader({});
var parser = reader.createAddressParser('test');
// Test that 0x values are parsed, and prevAddresses_ are untouched.
assertFalse('test' in reader.prevAddresses_);
assertEquals(0, parser('0x0'));
assertFalse('test' in reader.prevAddresses_);
assertEquals(0x100, parser('0x100'));
assertFalse('test' in reader.prevAddresses_);
assertEquals(0xffffffff, parser('0xffffffff'));
assertFalse('test' in reader.prevAddresses_);
// Test that values that has no '+' or '-' prefix are parsed
// and saved to prevAddresses_.
assertEquals(0, parser('0'));
assertEquals(0, reader.prevAddresses_.test);
assertEquals(0x100, parser('100'));
assertEquals(0x100, reader.prevAddresses_.test);
assertEquals(0xffffffff, parser('ffffffff'));
assertEquals(0xffffffff, reader.prevAddresses_.test);
// Test that values prefixed with '+' or '-' are treated as deltas,
// and prevAddresses_ is updated.
// Set base value.
assertEquals(0x100, parser('100'));
assertEquals(0x100, reader.prevAddresses_.test);
assertEquals(0x200, parser('+100'));
assertEquals(0x200, reader.prevAddresses_.test);
assertEquals(0x100, parser('-100'));
assertEquals(0x100, reader.prevAddresses_.test);
})();
(function testAddressParser() {
var reader = new devtools.profiler.LogReader({});
assertEquals([0x10000000, 0x10001000, 0xffff000, 0x10000000],
reader.processStack(0x10000000, ['overflow',
'+1000', '-2000', '+1000']));
})();
(function testExpandBackRef() {
var reader = new devtools.profiler.LogReader({});
assertEquals('aaaaaaaa', reader.expandBackRef_('aaaaaaaa'));
assertEquals('aaaaaaaa', reader.expandBackRef_('#1'));
assertEquals('bbbbaaaa', reader.expandBackRef_('bbbb#2:4'));
assertEquals('"#1:1"', reader.expandBackRef_('"#1:1"'));
})();
......@@ -12,4 +12,4 @@ d8_exec=$D8_PATH/d8
$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/tickprocessor.js -- $@ 2>/dev/null
$tools_path/logreader.js $tools_path/tickprocessor.js -- $@ 2>/dev/null
// 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.
/**
* @fileoverview Log Reader is used to process log file produced by V8.
*/
// Initlialize namespaces
var devtools = devtools || {};
devtools.profiler = devtools.profiler || {};
/**
* Base class for processing log files.
*
* @param {Array.<Object>} dispatchTable A table used for parsing and processing
* log records.
* @constructor
*/
devtools.profiler.LogReader = function(dispatchTable) {
/**
* @type {Array.<Object>}
*/
this.dispatchTable_ = dispatchTable;
this.dispatchTable_['alias'] =
{ parsers: [null, null], processor: this.processAlias_ };
this.dispatchTable_['repeat'] =
{ parsers: [parseInt, 'var-args'], processor: this.processRepeat_,
backrefs: true };
/**
* A key-value map for aliases. Translates short name -> full name.
* @type {Object}
*/
this.aliases_ = {};
/**
* A key-value map for previous address values.
* @type {Object}
*/
this.prevAddresses_ = {};
/**
* A key-value map for events than can be backreference-compressed.
* @type {Object}
*/
this.backRefsCommands_ = {};
this.initBackRefsCommands_();
/**
* Back references for decompression.
* @type {Array.<string>}
*/
this.backRefs_ = [];
};
/**
* Creates a parser for an address entry.
*
* @param {string} addressTag Address tag to perform offset decoding.
* @return {function(string):number} Address parser.
*/
devtools.profiler.LogReader.prototype.createAddressParser = function(
addressTag) {
var self = this;
return (function (str) {
var value = parseInt(str, 16);
var firstChar = str.charAt(0);
if (firstChar == '+' || firstChar == '-') {
var addr = self.prevAddresses_[addressTag];
addr += value;
self.prevAddresses_[addressTag] = addr;
return addr;
} else if (firstChar != '0' || str.charAt(1) != 'x') {
self.prevAddresses_[addressTag] = value;
}
return value;
});
};
/**
* Expands an alias symbol, if applicable.
*
* @param {string} symbol Symbol to expand.
* @return {string} Expanded symbol, or the input symbol itself.
*/
devtools.profiler.LogReader.prototype.expandAlias = function(symbol) {
return symbol in this.aliases_ ? this.aliases_[symbol] : symbol;
};
/**
* Used for printing error messages.
*
* @param {string} str Error message.
*/
devtools.profiler.LogReader.prototype.printError = function(str) {
// Do nothing.
};
/**
* Processes a portion of V8 profiler event log.
*
* @param {string} chunk A portion of log.
*/
devtools.profiler.LogReader.prototype.processLogChunk = function(chunk) {
this.processLog_(chunk.split('\n'));
};
/**
* Processes stack record.
*
* @param {number} pc Program counter.
* @param {Array.<string>} stack String representation of a stack.
* @return {Array.<number>} Processed stack.
*/
devtools.profiler.LogReader.prototype.processStack = function(pc, stack) {
var fullStack = [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));
}
}
return fullStack;
};
/**
* Returns whether a particular dispatch must be skipped.
*
* @param {!Object} dispatch Dispatch record.
* @return {boolean} True if dispatch must be skipped.
*/
devtools.profiler.LogReader.prototype.skipDispatch = function(dispatch) {
return false;
};
/**
* Does a dispatch of a log record.
*
* @param {Array.<string>} fields Log record.
* @private
*/
devtools.profiler.LogReader.prototype.dispatchLogRow_ = function(fields) {
// Obtain the dispatch.
var command = fields[0];
if (!(command in this.dispatchTable_)) {
throw new Error('unknown command: ' + command);
}
var dispatch = this.dispatchTable_[command];
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 === null) {
parsedFields.push(fields[1 + i]);
} else if (typeof parser == 'function') {
parsedFields.push(parser(fields[1 + i]));
} else {
// var-args
parsedFields.push(fields.slice(1 + i));
break;
}
}
// Run the processor.
dispatch.processor.apply(this, parsedFields);
};
/**
* Decompresses a line if it was backreference-compressed.
*
* @param {string} line Possibly compressed line.
* @return {string} Decompressed line.
* @private
*/
devtools.profiler.LogReader.prototype.expandBackRef_ = function(line) {
var backRefPos;
// Filter out case when a regexp is created containing '#'.
if (line.charAt(line.length - 1) != '"'
&& (backRefPos = line.lastIndexOf('#')) != -1) {
var backRef = line.substr(backRefPos + 1);
var backRefIdx = parseInt(backRef, 10) - 1;
var colonPos = backRef.indexOf(':');
var backRefStart =
colonPos != -1 ? parseInt(backRef.substr(colonPos + 1), 10) : 0;
line = line.substr(0, backRefPos) +
this.backRefs_[backRefIdx].substr(backRefStart);
}
this.backRefs_.unshift(line);
if (this.backRefs_.length > 10) {
this.backRefs_.length = 10;
}
return line;
};
/**
* Initializes the map of backward reference compressible commands.
* @private
*/
devtools.profiler.LogReader.prototype.initBackRefsCommands_ = function() {
for (var event in this.dispatchTable_) {
var dispatch = this.dispatchTable_[event];
if (dispatch && dispatch.backrefs) {
this.backRefsCommands_[event] = true;
}
}
};
/**
* Processes alias log record. Adds an alias to a corresponding map.
*
* @param {string} symbol Short name.
* @param {string} expansion Long name.
* @private
*/
devtools.profiler.LogReader.prototype.processAlias_ = function(
symbol, expansion) {
if (expansion in this.dispatchTable_) {
this.dispatchTable_[symbol] = this.dispatchTable_[expansion];
if (expansion in this.backRefsCommands_) {
this.backRefsCommands_[symbol] = true;
}
} else {
this.aliases_[symbol] = expansion;
}
};
/**
* Processes log lines.
*
* @param {Array.<string>} lines Log lines.
* @private
*/
devtools.profiler.LogReader.prototype.processLog_ = function(lines) {
var csvParser = new devtools.profiler.CsvParser();
try {
for (var i = 0, n = lines.length; i < n; ++i) {
var line = lines[i];
if (!line) {
continue;
}
if (line.charAt(0) == '#' ||
line.substr(0, line.indexOf(',')) in this.backRefsCommands_) {
line = this.expandBackRef_(line);
}
var fields = csvParser.parseLine(line);
this.dispatchLogRow_(fields);
}
} catch (e) {
this.printError('line ' + (i + 1) + ': ' + (e.message || e));
throw e;
}
};
/**
* Processes repeat log record. Expands it according to calls count and
* invokes processing.
*
* @param {number} count Count.
* @param {Array.<string>} cmd Parsed command.
* @private
*/
devtools.profiler.LogReader.prototype.processRepeat_ = function(count, cmd) {
// Replace the repeat-prefixed command from backrefs list with a non-prefixed.
this.backRefs_[0] = cmd.join(',');
for (var i = 0; i < count; ++i) {
this.dispatchLogRow_(cmd);
}
};
......@@ -52,8 +52,35 @@ function readFile(fileName) {
}
function inherits(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.prototype = new tempCtor();
};
function TickProcessor(
cppEntriesProvider, separateIc, ignoreUnknown, stateFilter) {
devtools.profiler.LogReader.call(this, {
'shared-library': { parsers: [null, parseInt, parseInt],
processor: this.processSharedLibrary },
'code-creation': {
parsers: [null, this.createAddressParser('code'), parseInt, null],
processor: this.processCodeCreation, backrefs: true },
'code-move': { parsers: [this.createAddressParser('code'),
this.createAddressParser('code-move-to')],
processor: this.processCodeMove, backrefs: true },
'code-delete': { parsers: [this.createAddressParser('code')],
processor: this.processCodeDelete, backrefs: true },
'tick': { parsers: [this.createAddressParser('code'),
this.createAddressParser('stack'), parseInt, 'var-args'],
processor: this.processTick, backrefs: true },
'profiler': null,
// Obsolete row types.
'code-allocate': null,
'begin-code-region': null,
'end-code-region': null });
this.cppEntriesProvider_ = cppEntriesProvider;
this.ignoreUnknown_ = ignoreUnknown;
this.stateFilter_ = stateFilter;
......@@ -86,8 +113,8 @@ function TickProcessor(
// Count each tick as a time unit.
this.viewBuilder_ = new devtools.profiler.ViewBuilder(1);
this.lastLogFileName_ = null;
this.aliases_ = {};
};
inherits(TickProcessor, devtools.profiler.LogReader);
TickProcessor.VmStates = {
......@@ -107,27 +134,17 @@ TickProcessor.CodeTypes = {
// codeTypes_ map because there can be zillions of them.
TickProcessor.RecordsDispatch = {
'shared-library': { parsers: [null, parseInt, parseInt],
processor: 'processSharedLibrary' },
'code-creation': { parsers: [null, parseInt, parseInt, null],
processor: 'processCodeCreation' },
'code-move': { parsers: [parseInt, parseInt],
processor: 'processCodeMove' },
'code-delete': { parsers: [parseInt], processor: 'processCodeDelete' },
'tick': { parsers: [parseInt, parseInt, parseInt, 'var-args'],
processor: 'processTick' },
'alias': { parsers: [null, null], processor: 'processAlias' },
'profiler': null,
// Obsolete row types.
'code-allocate': null,
'begin-code-region': null,
'end-code-region': null
};
TickProcessor.CALL_PROFILE_CUTOFF_PCT = 2.0;
/**
* @override
*/
TickProcessor.prototype.printError = function(str) {
print(str);
};
TickProcessor.prototype.setCodeType = function(name, type) {
this.codeTypes_[name] = TickProcessor.CodeTypes[type];
};
......@@ -151,52 +168,7 @@ TickProcessor.prototype.isJsCode = function(name) {
TickProcessor.prototype.processLogFile = function(fileName) {
this.lastLogFileName_ = fileName;
var contents = readFile(fileName);
this.processLog(contents.split('\n'));
};
TickProcessor.prototype.processLog = function(lines) {
var csvParser = new devtools.profiler.CsvParser();
for (var i = 0, n = lines.length; i < n; ++i) {
var line = lines[i];
if (!line) {
continue;
}
var fields = csvParser.parseLine(line);
this.dispatchLogRow(fields);
}
};
TickProcessor.prototype.dispatchLogRow = function(fields) {
// Obtain the dispatch.
var command = fields[0];
if (!(command in TickProcessor.RecordsDispatch)) {
throw new Error('unknown command: ' + command);
}
var dispatch = TickProcessor.RecordsDispatch[command];
if (dispatch === null) {
return;
}
// Parse fields.
var parsedFields = [];
for (var i = 0; i < dispatch.parsers.length; ++i) {
var parser = dispatch.parsers[i];
if (parser === null) {
parsedFields.push(fields[1 + i]);
} else if (typeof parser == 'function') {
parsedFields.push(parser(fields[1 + i]));
} else {
// var-args
parsedFields.push(fields.slice(1 + i));
break;
}
}
// Run the processor.
this[dispatch.processor].apply(this, parsedFields);
this.processLogChunk(contents);
};
......@@ -214,22 +186,10 @@ TickProcessor.prototype.processSharedLibrary = function(
};
TickProcessor.prototype.processAlias = function(symbol, expansion) {
if (expansion in TickProcessor.RecordsDispatch) {
TickProcessor.RecordsDispatch[symbol] =
TickProcessor.RecordsDispatch[expansion];
} else {
this.aliases_[symbol] = expansion;
}
};
TickProcessor.prototype.processCodeCreation = function(
type, start, size, name) {
if (type in this.aliases_) {
type = this.aliases_[type];
}
var entry = this.profile_.addCode(type, name, start, size);
var entry = this.profile_.addCode(
this.expandAlias(type), name, start, size);
};
......@@ -256,21 +216,7 @@ TickProcessor.prototype.processTick = function(pc, sp, vmState, stack) {
return;
}
var fullStack = [pc];
var prevFrame = pc;
for (var i = 0, n = stack.length; i < n; ++i) {
var frame = stack[i];
var firstChar = frame.charAt(0);
// Leave only numbers starting with 0x. Filter possible 'overflow' string.
if (firstChar == '0') {
fullStack.push(parseInt(frame, 16));
} else if (firstChar == '+' || firstChar == '-') {
// An offset from the previous frame.
prevFrame += parseInt(frame, 16);
fullStack.push(prevFrame);
}
}
this.profile_.recordTick(fullStack);
this.profile_.recordTick(this.processStack(pc, stack));
};
......@@ -464,13 +410,6 @@ CppEntriesProvider.prototype.parseNextLine = function() {
};
function inherits(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.prototype = new tempCtor();
};
function UnixCppEntriesProvider() {
this.symbols = [];
this.parsePos = 0;
......@@ -490,7 +429,7 @@ UnixCppEntriesProvider.prototype.loadSymbols = function(libName) {
];
} catch (e) {
// If the library cannot be found on this system let's not panic.
this.symbols = [ '', '' ];
this.symbols = ['', ''];
}
};
......
......@@ -2,4 +2,4 @@
SET tools_dir=%~dp0
%tools_dir%..\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%tickprocessor.js -- --windows %*
%tools_dir%..\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%tickprocessor.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