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);
}
}
}
+#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) {
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
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
}
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
}
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
}
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;
--- /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.
+
+// 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"'));
+})();
$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
--- /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);
+ }
+};
}
+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;
// 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 = {
// 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];
};
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);
};
};
-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);
};
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));
};
};
-function inherits(childCtor, parentCtor) {
- function tempCtor() {};
- tempCtor.prototype = parentCtor.prototype;
- childCtor.prototype = new tempCtor();
-};
-
-
function UnixCppEntriesProvider() {
this.symbols = [];
this.parsePos = 0;
];
} catch (e) {
// If the library cannot be found on this system let's not panic.
- this.symbols = [ '', '' ];
+ this.symbols = ['', ''];
}
};
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 %*