Revision: 3635
Author: [email protected]
Date: Mon Jan 18 08:04:25 2010
Log: Fix issue 571: display descriptive names for code objects from
snapshot.
As this is only needed for internal profiling (not for DevTools),
the following approach had been chosen:
- during snapshot creation, positions of serialized objects inside
a snapshot are logged;
- then during V8 initialization, positions of deserealized objects
are logged;
- those positions are used for retrieving code objects names from
snapshot creation log, which needs to be supplied to tick processor
script.
Positions logging is controlled with the new flag: --log_snapshot_positions.
This flag is turned off by default, and this adds no startup penalty.
To plug this fix to Golem, the following actions are needed:
- logs created using 'mksnapshot' need to be stored along with VM images;
- tick processor script needs to be run with '--snapshot-log=...' cmdline
argument.
BUG=571
Review URL: http://codereview.chromium.org/551062
http://code.google.com/p/v8/source/detail?r=3635
Modified:
/branches/bleeding_edge/src/SConscript
/branches/bleeding_edge/src/flag-definitions.h
/branches/bleeding_edge/src/log.cc
/branches/bleeding_edge/src/log.h
/branches/bleeding_edge/src/mksnapshot.cc
/branches/bleeding_edge/src/serialize.cc
/branches/bleeding_edge/src/serialize.h
/branches/bleeding_edge/src/snapshot-common.cc
/branches/bleeding_edge/tools/profile.js
/branches/bleeding_edge/tools/tickprocessor-driver.js
/branches/bleeding_edge/tools/tickprocessor.js
=======================================
--- /branches/bleeding_edge/src/SConscript Wed Dec 9 04:56:42 2009
+++ /branches/bleeding_edge/src/SConscript Mon Jan 18 08:04:25 2010
@@ -235,7 +235,7 @@
env.Replace(**context.flags['v8'])
context.ApplyEnvOverrides(env)
env['BUILDERS']['JS2C'] = Builder(action=js2c.JS2C)
- env['BUILDERS']['Snapshot'] = Builder(action='$SOURCE $TARGET
--logfile "$LOGFILE"')
+ env['BUILDERS']['Snapshot'] = Builder(action='$SOURCE $TARGET
--logfile "$LOGFILE" --log-snapshot-positions')
# Build the standard platform-independent source files.
source_files = context.GetRelevantSources(SOURCES)
=======================================
--- /branches/bleeding_edge/src/flag-definitions.h Thu Jan 7 11:01:23 2010
+++ /branches/bleeding_edge/src/flag-definitions.h Mon Jan 18 08:04:25 2010
@@ -358,6 +358,8 @@
DEFINE_bool(log_gc, false,
"Log heap samples on garbage collection for the hp2ps tool.")
DEFINE_bool(log_handles, false, "Log global handle events.")
+DEFINE_bool(log_snapshot_positions, false,
+ "log positions of (de)serialized objects in the snapshot.")
DEFINE_bool(log_state_changes, false, "Log state changes.")
DEFINE_bool(log_suspect, false, "Log suspect operations.")
DEFINE_bool(log_producers, false, "Log stack traces of JS objects
allocations.")
=======================================
--- /branches/bleeding_edge/src/log.cc Wed Nov 25 08:39:18 2009
+++ /branches/bleeding_edge/src/log.cc Mon Jan 18 08:04:25 2010
@@ -869,6 +869,23 @@
msg.WriteToLogFile();
#endif
}
+
+
+void Logger::SnapshotPositionEvent(Address addr, int pos) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+ if (!Log::IsEnabled() || !FLAG_log_snapshot_positions) return;
+ LogMessageBuilder msg;
+ msg.Append("%s,", log_events_[SNAPSHOT_POSITION_EVENT]);
+ msg.AppendAddress(addr);
+ msg.Append(",%d", pos);
+ if (FLAG_compress_log) {
+ ASSERT(compression_helper_ != NULL);
+ if (!compression_helper_->HandleMessage(&msg)) return;
+ }
+ msg.Append('\n');
+ msg.WriteToLogFile();
+#endif
+}
void Logger::ResourceEvent(const char* name, const char* tag) {
=======================================
--- /branches/bleeding_edge/src/log.h Wed Nov 25 08:39:18 2009
+++ /branches/bleeding_edge/src/log.h Mon Jan 18 08:04:25 2010
@@ -116,6 +116,7 @@
V(CODE_CREATION_EVENT, "code-creation", "cc") \
V(CODE_MOVE_EVENT, "code-move", "cm") \
V(CODE_DELETE_EVENT, "code-delete", "cd") \
+ V(SNAPSHOT_POSITION_EVENT, "snapshot-pos", "sp") \
V(TICK_EVENT, "tick", "t") \
V(REPEAT_META_EVENT, "repeat", "r") \
V(BUILTIN_TAG, "Builtin", "bi") \
@@ -224,6 +225,8 @@
// Emits a code delete event.
static void CodeDeleteEvent(Address from);
+ static void SnapshotPositionEvent(Address addr, int pos);
+
// ==== Events logged by --log-gc. ====
// Heap sampling events: start, end, and individual types.
static void HeapSampleBeginEvent(const char* space, const char* kind);
=======================================
--- /branches/bleeding_edge/src/mksnapshot.cc Mon Jan 11 23:16:49 2010
+++ /branches/bleeding_edge/src/mksnapshot.cc Mon Jan 18 08:04:25 2010
@@ -129,6 +129,10 @@
fprintf(fp_, "\n");
}
}
+
+ virtual int Position() {
+ return bytes_written_;
+ }
private:
FILE* fp_;
=======================================
--- /branches/bleeding_edge/src/serialize.cc Mon Jan 18 01:49:50 2010
+++ /branches/bleeding_edge/src/serialize.cc Mon Jan 18 08:04:25 2010
@@ -697,6 +697,9 @@
*write_back = HeapObject::FromAddress(address);
Object** current = reinterpret_cast<Object**>(address);
Object** limit = current + (size >> kPointerSizeLog2);
+ if (FLAG_log_snapshot_positions) {
+ LOG(SnapshotPositionEvent(address, source_->position()));
+ }
ReadChunk(current, limit, space_number, address);
}
@@ -1089,6 +1092,8 @@
}
sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
+ LOG(SnapshotPositionEvent(object_->address(), sink_->Position()));
+
// Mark this object as already serialized.
bool start_new_page;
SerializationAddressMapper::Map(
=======================================
--- /branches/bleeding_edge/src/serialize.h Fri Jan 15 06:20:31 2010
+++ /branches/bleeding_edge/src/serialize.h Mon Jan 18 08:04:25 2010
@@ -146,6 +146,8 @@
bool AtEOF() {
return position_ == length_;
}
+
+ const int position() { return position_; }
private:
const byte* data_;
@@ -294,6 +296,7 @@
Put(byte, description);
}
void PutInt(uintptr_t integer, const char* description);
+ virtual int Position() = 0;
};
=======================================
--- /branches/bleeding_edge/src/snapshot-common.cc Mon Nov 16 04:08:40 2009
+++ /branches/bleeding_edge/src/snapshot-common.cc Mon Jan 18 08:04:25 2010
@@ -79,6 +79,9 @@
fputc(byte, fp_);
}
}
+ virtual int Position() {
+ return ftell(fp_);
+ }
private:
FILE* fp_;
=======================================
--- /branches/bleeding_edge/tools/profile.js Tue Jul 14 02:47:44 2009
+++ /branches/bleeding_edge/tools/profile.js Mon Jan 18 08:04:25 2010
@@ -162,6 +162,16 @@
};
+/**
+ * Retrieves a code entry by an address.
+ *
+ * @param {number} addr Entry address.
+ */
+devtools.profiler.Profile.prototype.findEntry = function(addr) {
+ return this.codeMap_.findEntry(addr);
+};
+
+
/**
* Records a tick event. Stack must contain a sequence of
* addresses starting with the program counter value.
@@ -344,6 +354,14 @@
};
+/**
+ * Returns raw node name (without type decoration).
+ */
+devtools.profiler.Profile.DynamicCodeEntry.prototype.getRawName =
function() {
+ return this.name;
+};
+
+
/**
* Constructs a call graph.
*
=======================================
--- /branches/bleeding_edge/tools/tickprocessor-driver.js Mon Jul 13
22:01:06 2009
+++ /branches/bleeding_edge/tools/tickprocessor-driver.js Mon Jan 18
08:04:25 2010
@@ -44,10 +44,16 @@
};
var params = processArguments(arguments);
+var snapshotLogProcessor;
+if (params.snapshotLogFileName) {
+ snapshotLogProcessor = new SnapshotLogProcessor();
+ snapshotLogProcessor.processLogFile(params.snapshotLogFileName);
+}
var tickProcessor = new TickProcessor(
new (entriesProviders[params.platform])(params.nm),
params.separateIc,
params.ignoreUnknown,
- params.stateFilter);
+ params.stateFilter,
+ snapshotLogProcessor);
tickProcessor.processLogFile(params.logFileName);
tickProcessor.printStatistics();
=======================================
--- /branches/bleeding_edge/tools/tickprocessor.js Thu Oct 15 00:50:23 2009
+++ /branches/bleeding_edge/tools/tickprocessor.js Mon Jan 18 08:04:25 2010
@@ -53,14 +53,79 @@
function inherits(childCtor, parentCtor) {
- function tempCtor() {};
- tempCtor.prototype = parentCtor.prototype;
- childCtor.prototype = new tempCtor();
+ childCtor.prototype.__proto__ = parentCtor.prototype;
};
+function SnapshotLogProcessor() {
+ devtools.profiler.LogReader.call(this, {
+ '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 },
+ 'snapshot-pos': { parsers: [this.createAddressParser('code'),
parseInt],
+ processor: this.processSnapshotPosition, backrefs: true }});
+
+ Profile.prototype.handleUnknownCode = function(operation, addr) {
+ var op = devtools.profiler.Profile.Operation;
+ switch (operation) {
+ case op.MOVE:
+ print('Snapshot: Code move event for unknown code: 0x' +
+ addr.toString(16));
+ break;
+ case op.DELETE:
+ print('Snapshot: Code delete event for unknown code: 0x' +
+ addr.toString(16));
+ break;
+ }
+ };
+
+ this.profile_ = new Profile();
+ this.serializedEntries_ = [];
+}
+inherits(SnapshotLogProcessor, devtools.profiler.LogReader);
+
+
+SnapshotLogProcessor.prototype.processCodeCreation = function(
+ type, start, size, name) {
+ var entry = this.profile_.addCode(
+ this.expandAlias(type), name, start, size);
+};
+
+
+SnapshotLogProcessor.prototype.processCodeMove = function(from, to) {
+ this.profile_.moveCode(from, to);
+};
+
+
+SnapshotLogProcessor.prototype.processCodeDelete = function(start) {
+ this.profile_.deleteCode(start);
+};
+
+
+SnapshotLogProcessor.prototype.processSnapshotPosition = function(addr,
pos) {
+ this.serializedEntries_[pos] = this.profile_.findEntry(addr);
+};
+
+
+SnapshotLogProcessor.prototype.processLogFile = function(fileName) {
+ var contents = readFile(fileName);
+ this.processLogChunk(contents);
+};
+
+
+SnapshotLogProcessor.prototype.getSerializedEntryName = function(pos) {
+ var entry = this.serializedEntries_[pos];
+ return entry ? entry.getRawName() : null;
+};
+
+
function TickProcessor(
- cppEntriesProvider, separateIc, ignoreUnknown, stateFilter) {
+ cppEntriesProvider, separateIc, ignoreUnknown, stateFilter,
snapshotLogProcessor) {
devtools.profiler.LogReader.call(this, {
'shared-library': { parsers: [null, parseInt, parseInt],
processor: this.processSharedLibrary },
@@ -72,6 +137,8 @@
processor: this.processCodeMove, backrefs: true },
'code-delete': { parsers: [this.createAddressParser('code')],
processor: this.processCodeDelete, backrefs: true },
+ 'snapshot-pos': { parsers: [this.createAddressParser('code'),
parseInt],
+ processor: this.processSnapshotPosition, backrefs: true },
'tick': { parsers: [this.createAddressParser('code'),
this.createAddressParser('stack'), parseInt, 'var-args'],
processor: this.processTick, backrefs: true },
@@ -95,6 +162,8 @@
this.cppEntriesProvider_ = cppEntriesProvider;
this.ignoreUnknown_ = ignoreUnknown;
this.stateFilter_ = stateFilter;
+ this.snapshotLogProcessor_ = snapshotLogProcessor;
+ this.deserializedEntriesNames_ = [];
var ticks = this.ticks_ =
{ total: 0, unaccounted: 0, excluded: 0, gc: 0 };
@@ -202,6 +271,7 @@
TickProcessor.prototype.processCodeCreation = function(
type, start, size, name) {
+ name = this.deserializedEntriesNames_[start] || name;
var entry = this.profile_.addCode(
this.expandAlias(type), name, start, size);
};
@@ -217,6 +287,14 @@
};
+TickProcessor.prototype.processSnapshotPosition = function(addr, pos) {
+ if (this.snapshotLogProcessor_) {
+ this.deserializedEntriesNames_[addr] =
+ this.snapshotLogProcessor_.getSerializedEntryName(pos);
+ }
+};
+
+
TickProcessor.prototype.includeTick = function(vmState) {
return this.stateFilter_ == null || this.stateFilter_ == vmState;
};
@@ -648,7 +726,9 @@
'--mac': ['platform', 'mac',
'Specify that we are running on Mac OS X platform'],
'--nm': ['nm', 'nm',
- 'Specify the \'nm\' executable to use (e.g. --nm=/my_dir/nm)']
+ 'Specify the \'nm\' executable to use (e.g. --nm=/my_dir/nm)'],
+ '--snapshot-log': ['snapshotLogFileName', 'snapshot.log',
+ 'Specify snapshot log file to use (e.g.
--snapshot-log=snapshot.log)']
};
this.argsDispatch_['--js'] = this.argsDispatch_['-j'];
this.argsDispatch_['--gc'] = this.argsDispatch_['-g'];
@@ -660,6 +740,7 @@
ArgumentsProcessor.DEFAULTS = {
logFileName: 'v8.log',
+ snapshotLogFileName: null,
platform: 'unix',
stateFilter: null,
ignoreUnknown: false,
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev