New version of v8 from bleeding edge at revision 3649
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index ba7224b..4368eb8 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -199,9 +199,7 @@
'conditions': [
# The ARM assembler assumes the host is 32 bits, so force building
# 32-bit host tools.
- # TODO(piman): This assumes that the host is ia32 or amd64. Fixing the
- # code would be better
- ['target_arch=="arm" and _toolset=="host"', {
+ ['target_arch=="arm" and host_arch=="x64" and _toolset=="host"', {
'cflags': ['-m32'],
'ldflags': ['-m32'],
}]
@@ -428,9 +426,7 @@
'conditions': [
# The ARM assembler assumes the host is 32 bits, so force building
# 32-bit host tools.
- # TODO(piman): This assumes that the host is ia32 or amd64. Fixing
- # the code would be better
- ['_toolset=="host"', {
+ ['host_arch=="x64" and _toolset=="host"', {
'cflags': ['-m32'],
'ldflags': ['-m32'],
}]
@@ -598,9 +594,7 @@
'conditions': [
# The ARM assembler assumes the host is 32 bits, so force building
# 32-bit host tools.
- # TODO(piman): This assumes that the host is ia32 or amd64. Fixing
- # the code would be better
- ['target_arch=="arm" and _toolset=="host"', {
+ ['target_arch=="arm" and host_arch=="x64" and _toolset=="host"', {
'cflags': ['-m32'],
'ldflags': ['-m32'],
}]
diff --git a/tools/jsmin.py b/tools/jsmin.py
index fd1abe4..646bf14 100644
--- a/tools/jsmin.py
+++ b/tools/jsmin.py
@@ -230,7 +230,9 @@
# A regexp that matches a literal string surrounded by 'double quotes'.
single_quoted_string = r"'(?:[^'\\]|\\.)*'"
# A regexp that matches a regexp literal surrounded by /slashes/.
- slash_quoted_regexp = r"/(?:[^/\\]|\\.)+/"
+ # Don't allow a regexp to have a ) before the first ( since that's a
+ # syntax error and it's probably just two unrelated slashes.
+ slash_quoted_regexp = r"/(?:(?=\()|(?:[^()/\\]|\\.)+)(?:\([^/\\]|\\.)*/"
# Replace multiple spaces with a single space.
line = re.sub("|".join([double_quoted_string,
single_quoted_string,
diff --git a/tools/presubmit.py b/tools/presubmit.py
index 3f27c00..04952e0 100755
--- a/tools/presubmit.py
+++ b/tools/presubmit.py
@@ -221,7 +221,7 @@
COPYRIGHT_HEADER_PATTERN = re.compile(
- r'Copyright [\d-]*200[8-9] the V8 project authors. All rights reserved.')
+ r'Copyright [\d-]*20[0-1][0-9] the V8 project authors. All rights reserved.')
class SourceProcessor(SourceFileProcessor):
"""
diff --git a/tools/profile.js b/tools/profile.js
index db4b542..d41f5cd 100644
--- a/tools/profile.js
+++ b/tools/profile.js
@@ -163,6 +163,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.
*
@@ -345,6 +355,14 @@
/**
+ * Returns raw node name (without type decoration).
+ */
+devtools.profiler.Profile.DynamicCodeEntry.prototype.getRawName = function() {
+ return this.name;
+};
+
+
+/**
* Constructs a call graph.
*
* @constructor
diff --git a/tools/stats-viewer.py b/tools/stats-viewer.py
index bd6a8fb..14b2147 100755
--- a/tools/stats-viewer.py
+++ b/tools/stats-viewer.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python
+#
# Copyright 2008 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
@@ -35,6 +37,7 @@
import mmap
import os
+import re
import struct
import sys
import time
@@ -49,8 +52,9 @@
COUNTER_LABELS = {"t": "%i ms.", "c": "%i"}
-# The magic number used to check if a file is not a counters file
+# The magic numbers used to check if a file is not a counters file
COUNTERS_FILE_MAGIC_NUMBER = 0xDEADFACE
+CHROME_COUNTERS_FILE_MAGIC_NUMBER = 0x13131313
class StatsViewer(object):
@@ -92,17 +96,31 @@
something goes wrong print an informative message and exit the
program."""
if not os.path.exists(self.data_name):
- print "File %s doesn't exist." % self.data_name
- sys.exit(1)
+ maps_name = "/proc/%s/maps" % self.data_name
+ if not os.path.exists(maps_name):
+ print "\"%s\" is neither a counter file nor a PID." % self.data_name
+ sys.exit(1)
+ maps_file = open(maps_name, "r")
+ try:
+ m = re.search(r"/dev/shm/\S*", maps_file.read())
+ if m is not None and os.path.exists(m.group(0)):
+ self.data_name = m.group(0)
+ else:
+ print "Can't find counter file in maps for PID %s." % self.data_name
+ sys.exit(1)
+ finally:
+ maps_file.close()
data_file = open(self.data_name, "r")
size = os.fstat(data_file.fileno()).st_size
fileno = data_file.fileno()
self.shared_mmap = mmap.mmap(fileno, size, access=mmap.ACCESS_READ)
data_access = SharedDataAccess(self.shared_mmap)
- if data_access.IntAt(0) != COUNTERS_FILE_MAGIC_NUMBER:
- print "File %s is not stats data." % self.data_name
- sys.exit(1)
- return CounterCollection(data_access)
+ if data_access.IntAt(0) == COUNTERS_FILE_MAGIC_NUMBER:
+ return CounterCollection(data_access)
+ elif data_access.IntAt(0) == CHROME_COUNTERS_FILE_MAGIC_NUMBER:
+ return ChromeCounterCollection(data_access)
+ print "File %s is not stats data." % self.data_name
+ sys.exit(1)
def CleanUp(self):
"""Cleans up the memory mapped file if necessary."""
@@ -356,6 +374,72 @@
return 4 + self.max_name_size
+class ChromeCounter(object):
+ """A pointer to a single counter withing a binary counters file."""
+
+ def __init__(self, data, name_offset, value_offset):
+ """Create a new instance.
+
+ Args:
+ data: the shared data access object containing the counter
+ name_offset: the byte offset of the start of this counter's name
+ value_offset: the byte offset of the start of this counter's value
+ """
+ self.data = data
+ self.name_offset = name_offset
+ self.value_offset = value_offset
+
+ def Value(self):
+ """Return the integer value of this counter."""
+ return self.data.IntAt(self.value_offset)
+
+ def Name(self):
+ """Return the ascii name of this counter."""
+ result = ""
+ index = self.name_offset
+ current = self.data.ByteAt(index)
+ while current:
+ result += chr(current)
+ index += 1
+ current = self.data.ByteAt(index)
+ return result
+
+
+class ChromeCounterCollection(object):
+ """An overlay over a counters file that provides access to the
+ individual counters contained in the file."""
+
+ _HEADER_SIZE = 4 * 4
+ _NAME_SIZE = 32
+
+ def __init__(self, data):
+ """Create a new instance.
+
+ Args:
+ data: the shared data access object
+ """
+ self.data = data
+ self.max_counters = data.IntAt(8)
+ self.max_threads = data.IntAt(12)
+ self.counter_names_offset = \
+ self._HEADER_SIZE + self.max_threads * (self._NAME_SIZE + 2 * 4)
+ self.counter_values_offset = \
+ self.counter_names_offset + self.max_counters * self._NAME_SIZE
+
+ def CountersInUse(self):
+ """Return the number of counters in active use."""
+ for i in xrange(self.max_counters):
+ if self.data.ByteAt(self.counter_names_offset + i * self._NAME_SIZE) == 0:
+ return i
+ return self.max_counters
+
+ def Counter(self, i):
+ """Return the i'th counter."""
+ return ChromeCounter(self.data,
+ self.counter_names_offset + i * self._NAME_SIZE,
+ self.counter_values_offset + i * self.max_threads * 4)
+
+
def Main(data_file):
"""Run the stats counter.
@@ -367,6 +451,6 @@
if __name__ == "__main__":
if len(sys.argv) != 2:
- print "Usage: stats-viewer.py <stats data>"
+ print "Usage: stats-viewer.py <stats data>|<test_shell pid>"
sys.exit(1)
Main(sys.argv[1])
diff --git a/tools/test.py b/tools/test.py
index 75b4f61..f17e9b1 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -639,10 +639,7 @@
name = name + '.exe'
return name
-def RunTestCases(all_cases, progress, tasks):
- def DoSkip(case):
- return SKIP in c.outcomes or SLOW in c.outcomes
- cases_to_run = [ c for c in all_cases if not DoSkip(c) ]
+def RunTestCases(cases_to_run, progress, tasks):
progress = PROGRESS_INDICATORS[progress](cases_to_run)
return progress.Run(tasks)
@@ -1335,13 +1332,16 @@
PrintReport(all_cases)
result = None
- if len(all_cases) == 0:
+ def DoSkip(case):
+ return SKIP in case.outcomes or SLOW in case.outcomes
+ cases_to_run = [ c for c in all_cases if not DoSkip(c) ]
+ if len(cases_to_run) == 0:
print "No tests to run."
return 0
else:
try:
start = time.time()
- if RunTestCases(all_cases, options.progress, options.j):
+ if RunTestCases(cases_to_run, options.progress, options.j):
result = 0
else:
result = 1
@@ -1355,7 +1355,7 @@
# test output.
print
sys.stderr.write("--- Total time: %s ---\n" % FormatTime(duration))
- timed_tests = [ t.case for t in all_cases if not t.case.duration is None ]
+ timed_tests = [ t.case for t in cases_to_run if not t.case.duration is None ]
timed_tests.sort(lambda a, b: a.CompareTime(b))
index = 1
for entry in timed_tests[:20]:
diff --git a/tools/tickprocessor-driver.js b/tools/tickprocessor-driver.js
index dc67796..4201e43 100644
--- a/tools/tickprocessor-driver.js
+++ b/tools/tickprocessor-driver.js
@@ -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();
diff --git a/tools/tickprocessor.js b/tools/tickprocessor.js
index fd23987..c566c22 100644
--- a/tools/tickprocessor.js
+++ b/tools/tickprocessor.js
@@ -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,