Author: [email protected]
Date: Thu Feb 19 05:07:13 2009
New Revision: 1316
Modified:
branches/experimental/toiger/ (props changed)
branches/experimental/toiger/samples/shell.cc
branches/experimental/toiger/src/array.js
branches/experimental/toiger/src/flag-definitions.h
branches/experimental/toiger/src/log.cc
branches/experimental/toiger/src/log.h
branches/experimental/toiger/src/platform-freebsd.cc
branches/experimental/toiger/src/platform-linux.cc
branches/experimental/toiger/src/platform-macos.cc
branches/experimental/toiger/src/platform-win32.cc
branches/experimental/toiger/src/platform.h
branches/experimental/toiger/src/regexp-macro-assembler-irregexp-inl.h
(props changed)
branches/experimental/toiger/src/runtime.cc
branches/experimental/toiger/tools/linux-tick-processor.py
branches/experimental/toiger/tools/tickprocessor.py
branches/experimental/toiger/tools/windows-tick-processor.py
Log:
Experimental: periodic merge from bleeding_edge. Merge revisions
r1277 through r1297 inclusive.
Modified: branches/experimental/toiger/samples/shell.cc
==============================================================================
--- branches/experimental/toiger/samples/shell.cc (original)
+++ branches/experimental/toiger/samples/shell.cc Thu Feb 19 05:07:13 2009
@@ -141,7 +141,7 @@
return v8::ThrowException(v8::String::New("Error loading file"));
}
if (!ExecuteString(source, v8::String::New(*file), false, false)) {
- return v8::ThrowException(v8::String::New("Error executing file"));
+ return v8::ThrowException(v8::String::New("Error executing file"));
}
}
return v8::Undefined();
Modified: branches/experimental/toiger/src/array.js
==============================================================================
--- branches/experimental/toiger/src/array.js (original)
+++ branches/experimental/toiger/src/array.js Thu Feb 19 05:07:13 2009
@@ -683,29 +683,26 @@
(custom_compare || %_IsSmi(pivot)) ? pivot : ToString(pivot);
// Issue 95: Keep the pivot element out of the comparisons to avoid
// infinite recursion if comparefn(pivot, pivot) != 0.
- var low_end = from; // Upper bound of the elements lower than pivot.
- var high_start = to; // Lower bound of the elements greater than pivot.
- var eq_start = to - 1; // Lower bound of elements equal to pivot.
- a[pivot_index] = a[eq_start];
- a[eq_start] = pivot;
- // From eq_start to high_start are elements equal to the pivot
- // (including the pivot).
- // From low_end to eq_start are elements that have not been compared
yet.
- while (low_end < eq_start) {
- var element = a[low_end];
+ a[pivot_index] = a[from];
+ a[from] = pivot;
+ var low_end = from; // Upper bound of the elements lower than pivot.
+ var high_start = to; // Lower bound of the elements greater than
pivot.
+ // From low_end to i are elements equal to pivot.
+ // From i to high_start are elements that haven't been compared yet.
+ for (var i = from + 1; i < high_start; ) {
+ var element = a[i];
var order = Compare(element, pivot_key);
if (order < 0) {
+ a[i] = a[low_end];
+ a[low_end] = element;
+ i++;
low_end++;
} else if (order > 0) {
- eq_start--;
high_start--;
- a[low_end] = a[eq_start];
- a[eq_start] = a[high_start];
+ a[i] = a[high_start];
a[high_start] = element;
} else { // order == 0
- eq_start--;
- a[low_end] = a[eq_start];
- a[eq_start] = element;
+ i++;
}
}
QuickSort(a, from, low_end);
Modified: branches/experimental/toiger/src/flag-definitions.h
==============================================================================
--- branches/experimental/toiger/src/flag-definitions.h (original)
+++ branches/experimental/toiger/src/flag-definitions.h Thu Feb 19 05:07:13
2009
@@ -315,6 +315,7 @@
DEFINE_bool(log, false,
"Minimal logging (no API, code, GC, suspect, or handles
samples).")
DEFINE_bool(log_all, false, "Log all events to the log file.")
+DEFINE_bool(log_runtime, false, "Activate runtime system %Log call.")
DEFINE_bool(log_api, false, "Log API events to the log file.")
DEFINE_bool(log_code, false,
"Log code events to the log file without profiling.")
Modified: branches/experimental/toiger/src/log.cc
==============================================================================
--- branches/experimental/toiger/src/log.cc (original)
+++ branches/experimental/toiger/src/log.cc Thu Feb 19 05:07:13 2009
@@ -139,12 +139,14 @@
//
class Ticker: public Sampler {
public:
- explicit Ticker(int interval):
- Sampler(interval, FLAG_prof), window_(NULL), profiler_(NULL) {}
+ explicit Ticker(int interval, unsigned int low_stack_bound):
+ Sampler(interval, FLAG_prof), window_(NULL), profiler_(NULL),
+ low_stack_bound_(low_stack_bound) {}
~Ticker() { if (IsActive()) Stop(); }
void Tick(TickSample* sample) {
+ if (IsProfiling()) SampleStack(sample);
if (profiler_) profiler_->Insert(sample);
if (window_) window_->AddState(sample->state);
}
@@ -170,8 +172,21 @@
}
private:
+ void SampleStack(TickSample* sample) {
+ // Assuming that stack grows from lower addresses
+ if (sample->sp < sample->fp && sample->fp < low_stack_bound_) {
+ sample->InitStack(1);
+ sample->stack[0] = Memory::Address_at(
+ (Address)(sample->fp + StandardFrameConstants::kCallerPCOffset));
+ } else {
+ // FP seems to be in some intermediate state, better discard this
sample
+ sample->InitStack(0);
+ }
+ }
+
SlidingStateWindow* window_;
Profiler* profiler_;
+ unsigned int low_stack_bound_;
};
@@ -239,9 +254,6 @@
// the thread to terminate.
running_ = false;
TickSample sample;
- sample.pc = 0;
- sample.sp = 0;
- sample.state = OTHER;
Insert(&sample);
Join();
@@ -259,10 +271,125 @@
}
+#ifdef ENABLE_LOGGING_AND_PROFILING
+// Utility class for formatting log messages. It fills the message into the
+// static buffer in Logger.
+class LogMessageBuilder BASE_EMBEDDED {
+ public:
+ explicit LogMessageBuilder();
+ ~LogMessageBuilder() { }
+
+ void Append(const char* format, ...);
+ void Append(const char* format, va_list args);
+ void Append(const char c);
+ void Append(String *str);
+ void AppendDetailed(String* str, bool show_impl_info);
+
+ void WriteToLogFile();
+
+ private:
+ ScopedLock sl;
+ int pos_;
+};
+
+
+// Create a message builder starting from position 0. This acquires the
mutex
+// in the logger as well.
+LogMessageBuilder::LogMessageBuilder(): sl(Logger::mutex_), pos_(0) {
+ ASSERT(Logger::message_buffer_ != NULL);
+}
+
+
+// Append string data to the log message.
+void LogMessageBuilder::Append(const char* format, ...) {
+ Vector<char> buf(Logger::message_buffer_ + pos_,
+ Logger::kMessageBufferSize - pos_);
+ va_list args;
+ va_start(args, format);
+ Append(format, args);
+ va_end(args);
+ ASSERT(pos_ <= Logger::kMessageBufferSize);
+}
+
+
+// Append string data to the log message.
+void LogMessageBuilder::Append(const char* format, va_list args) {
+ Vector<char> buf(Logger::message_buffer_ + pos_,
+ Logger::kMessageBufferSize - pos_);
+ int result = v8::internal::OS::VSNPrintF(buf, format, args);
+
+ // Result is -1 if output was truncated.
+ if (result >= 0) {
+ pos_ += result;
+ } else {
+ pos_ = Logger::kMessageBufferSize;
+ }
+ ASSERT(pos_ <= Logger::kMessageBufferSize);
+}
+
+
+// Append a character to the log message.
+void LogMessageBuilder::Append(const char c) {
+ if (pos_ < Logger::kMessageBufferSize) {
+ Logger::message_buffer_[pos_++] = c;
+ }
+ ASSERT(pos_ <= Logger::kMessageBufferSize);
+}
+
+
+// Append a heap string.
+void LogMessageBuilder::Append(String* str) {
+ AssertNoAllocation no_heap_allocation; // Ensure string stay valid.
+ StringShape shape(str);
+ int length = str->length(shape);
+ for (int i = 0; i < length; i++) {
+ Append(static_cast<char>(str->Get(shape, i)));
+ }
+}
+
+void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
+ AssertNoAllocation no_heap_allocation; // Ensure string stay valid.
+ StringShape shape(str);
+ int len = str->length(shape);
+ if (len > 0x1000)
+ len = 0x1000;
+ if (show_impl_info) {
+ Append(shape.IsAsciiRepresentation() ? 'a' : '2');
+ if (shape.IsExternal())
+ Append('e');
+ if (shape.IsSymbol())
+ Append('#');
+ Append(":%i:", str->length());
+ }
+ for (int i = 0; i < len; i++) {
+ uc32 c = str->Get(shape, i);
+ if (c > 0xff) {
+ Append("\\u%04x", c);
+ } else if (c < 32 || c > 126) {
+ Append("\\x%02x", c);
+ } else if (c == ',') {
+ Append("\\,");
+ } else if (c == '\\') {
+ Append("\\\\");
+ } else {
+ Append("%lc", c);
+ }
+ }
+}
+
+// Write the log message to the log file currently opened.
+void LogMessageBuilder::WriteToLogFile() {
+ ASSERT(pos_ <= Logger::kMessageBufferSize);
+ fwrite(Logger::message_buffer_, 1, pos_, Logger::logfile_);
+}
+#endif
+
+
//
// Logger class implementation.
//
Ticker* Logger::ticker_ = NULL;
+char* Logger::message_buffer_ = NULL;
FILE* Logger::logfile_ = NULL;
Profiler* Logger::profiler_ = NULL;
Mutex* Logger::mutex_ = NULL;
@@ -271,11 +398,13 @@
#endif // ENABLE_LOGGING_AND_PROFILING
+
void Logger::Preamble(const char* content) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_code) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "%s", content);
+ LogMessageBuilder msg;
+ msg.Append("%s", content);
+ msg.WriteToLogFile();
#endif
}
@@ -290,8 +419,9 @@
#ifdef ENABLE_LOGGING_AND_PROFILING
void Logger::UncheckedStringEvent(const char* name, const char* value) {
if (logfile_ == NULL) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "%s,\"%s\"\n", name, value);
+ LogMessageBuilder msg;
+ msg.Append("%s,\"%s\"\n", name, value);
+ msg.WriteToLogFile();
}
#endif
@@ -299,8 +429,9 @@
void Logger::IntEvent(const char* name, int value) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "%s,%d\n", name, value);
+ LogMessageBuilder msg;
+ msg.Append("%s,%d\n", name, value);
+ msg.WriteToLogFile();
#endif
}
@@ -308,9 +439,10 @@
void Logger::HandleEvent(const char* name, Object** location) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_handles) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "%s,0x%x\n", name,
- reinterpret_cast<unsigned int>(location));
+ LogMessageBuilder msg;
+ msg.Append("%s,0x%x\n", name,
+ reinterpret_cast<unsigned int>(location));
+ msg.WriteToLogFile();
#endif
}
@@ -321,10 +453,12 @@
// FLAG_log_api is true.
void Logger::ApiEvent(const char* format, ...) {
ASSERT(logfile_ != NULL && FLAG_log_api);
- ScopedLock sl(mutex_);
+ LogMessageBuilder msg;
va_list ap;
va_start(ap, format);
- vfprintf(logfile_, format, ap);
+ msg.Append(format, ap);
+ va_end(ap);
+ msg.WriteToLogFile();
}
#endif
@@ -350,9 +484,10 @@
unsigned end) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_prof) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "shared-library,\"%s\",0x%08x,0x%08x\n", library_path,
- start, end);
+ LogMessageBuilder msg;
+ msg.Append("shared-library,\"%s\",0x%08x,0x%08x\n", library_path,
+ start, end);
+ msg.WriteToLogFile();
#endif
}
@@ -362,79 +497,54 @@
unsigned end) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_prof) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "shared-library,\"%ls\",0x%08x,0x%08x\n", library_path,
- start, end);
+ LogMessageBuilder msg;
+ msg.Append("shared-library,\"%ls\",0x%08x,0x%08x\n", library_path,
+ start, end);
+ msg.WriteToLogFile();
#endif
}
#ifdef ENABLE_LOGGING_AND_PROFILING
-void Logger::LogString(Handle<String> str, bool show_impl_info) {
- StringShape shape(*str);
- int len = str->length(shape);
- if (len > 0x1000)
- len = 0x1000;
- if (show_impl_info) {
- fputc(shape.IsAsciiRepresentation() ? 'a' : '2', logfile_);
- if (shape.IsExternal())
- fputc('e', logfile_);
- if (shape.IsSymbol())
- fputc('#', logfile_);
- fprintf(logfile_, ":%i:", str->length());
- }
- for (int i = 0; i < len; i++) {
- uc32 c = str->Get(shape, i);
- if (c > 0xff) {
- fprintf(logfile_, "\\u%04x", c);
- } else if (c < 32 || c > 126) {
- fprintf(logfile_, "\\x%02x", c);
- } else if (c == ',') {
- fprintf(logfile_, "\\,");
- } else if (c == '\\') {
- fprintf(logfile_, "\\\\");
- } else {
- fprintf(logfile_, "%lc", c);
- }
- }
-}
-
void Logger::LogRegExpSource(Handle<JSRegExp> regexp) {
// Prints "/" + re.source + "/" +
// (re.global?"g":"") + (re.ignorecase?"i":"") +
(re.multiline?"m":"")
+ LogMessageBuilder msg;
Handle<Object> source = GetProperty(regexp, "source");
if (!source->IsString()) {
- fprintf(logfile_, "no source");
+ msg.Append("no source");
return;
}
switch (regexp->TypeTag()) {
case JSRegExp::ATOM:
- fprintf(logfile_, "a");
+ msg.Append('a');
break;
default:
break;
}
- fprintf(logfile_, "/");
- LogString(Handle<String>::cast(source), false);
- fprintf(logfile_, "/");
+ msg.Append('/');
+ msg.AppendDetailed(*Handle<String>::cast(source), false);
+ msg.Append('/');
// global flag
Handle<Object> global = GetProperty(regexp, "global");
if (global->IsTrue()) {
- fprintf(logfile_, "g");
+ msg.Append('g');
}
// ignorecase flag
Handle<Object> ignorecase = GetProperty(regexp, "ignoreCase");
if (ignorecase->IsTrue()) {
- fprintf(logfile_, "i");
+ msg.Append('i');
}
// multiline flag
Handle<Object> multiline = GetProperty(regexp, "multiline");
if (multiline->IsTrue()) {
- fprintf(logfile_, "m");
+ msg.Append('m');
}
+
+ msg.WriteToLogFile();
}
#endif // ENABLE_LOGGING_AND_PROFILING
@@ -442,19 +552,20 @@
void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_regexp) return;
- ScopedLock sl(mutex_);
-
- fprintf(logfile_, "regexp-compile,");
+ LogMessageBuilder msg;
+ msg.Append("regexp-compile,");
LogRegExpSource(regexp);
- fprintf(logfile_, in_cache ? ",hit\n" : ",miss\n");
+ msg.Append(in_cache ? ",hit\n" : ",miss\n");
+ msg.WriteToLogFile();
#endif
}
void Logger::LogRuntime(Vector<const char> format, JSArray* args) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- ScopedLock sl(mutex_);
+ if (logfile_ == NULL || !FLAG_log_runtime) return;
HandleScope scope;
+ LogMessageBuilder msg;
for (int i = 0; i < format.length(); i++) {
char c = format[i];
if (c == '%' && i <= format.length() - 2) {
@@ -464,28 +575,29 @@
i++;
switch (format[i]) {
case 's':
- Logger::LogString(Handle<String>(String::cast(obj)), false);
+ msg.AppendDetailed(String::cast(obj), false);
break;
case 'S':
- Logger::LogString(Handle<String>(String::cast(obj)), true);
+ msg.AppendDetailed(String::cast(obj), true);
break;
case 'r':
Logger::LogRegExpSource(Handle<JSRegExp>(JSRegExp::cast(obj)));
break;
case 'x':
- fprintf(logfile_, "0x%x", Smi::cast(obj)->value());
+ msg.Append("0x%x", Smi::cast(obj)->value());
break;
case 'i':
- fprintf(logfile_, "%i", Smi::cast(obj)->value());
+ msg.Append("%i", Smi::cast(obj)->value());
break;
default:
UNREACHABLE();
}
} else {
- fputc(c, logfile_);
+ msg.Append(c);
}
}
- fputc('\n', logfile_);
+ msg.Append('\n');
+ msg.WriteToLogFile();
#endif
}
@@ -547,10 +659,11 @@
void Logger::NewEvent(const char* name, void* object, size_t size) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "new,%s,0x%x,%u\n", name,
- reinterpret_cast<unsigned int>(object),
- static_cast<unsigned int>(size));
+ LogMessageBuilder msg;
+ msg.Append("new,%s,0x%x,%u\n", name,
+ reinterpret_cast<unsigned int>(object),
+ static_cast<unsigned int>(size));
+ msg.WriteToLogFile();
#endif
}
@@ -558,26 +671,39 @@
void Logger::DeleteEvent(const char* name, void* object) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "delete,%s,0x%x\n", name,
- reinterpret_cast<unsigned int>(object));
+ LogMessageBuilder msg;
+ msg.Append("delete,%s,0x%x\n", name,
+ reinterpret_cast<unsigned int>(object));
+ msg.WriteToLogFile();
#endif
}
+int Logger::CodeObjectSize(Code* code) {
+ // Check that the assumptions about the layout of the code object holds.
+ ASSERT_EQ(reinterpret_cast<unsigned int>(code->instruction_start()) -
+ reinterpret_cast<unsigned int>(code->address()),
+ Code::kHeaderSize);
+ return code->instruction_size() + Code::kHeaderSize;
+}
+
+
void Logger::CodeCreateEvent(const char* tag, Code* code, const char*
comment) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_code) return;
- ScopedLock sl(mutex_);
-
- fprintf(logfile_, "code-creation,%s,0x%x,%d,\"", tag,
- reinterpret_cast<unsigned int>(code->address()),
- code->instruction_size());
+ LogMessageBuilder msg;
+ msg.Append("code-creation,%s,0x%x,%d,\"", tag,
+ reinterpret_cast<unsigned int>(code->address()),
+ CodeObjectSize(code));
for (const char* p = comment; *p != '\0'; p++) {
- if (*p == '\"') fprintf(logfile_, "\\");
- fprintf(logfile_, "%c", *p);
+ if (*p == '"') {
+ msg.Append('\\');
+ }
+ msg.Append(*p);
}
- fprintf(logfile_, "\"\n");
+ msg.Append('"');
+ msg.Append('\n');
+ msg.WriteToLogFile();
#endif
}
@@ -585,12 +711,13 @@
void Logger::CodeCreateEvent(const char* tag, Code* code, String* name) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_code) return;
- ScopedLock sl(mutex_);
+ LogMessageBuilder msg;
SmartPointer<char> str =
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- fprintf(logfile_, "code-creation,%s,0x%x,%d,\"%s\"\n", tag,
- reinterpret_cast<unsigned int>(code->address()),
- code->instruction_size(), *str);
+ msg.Append("code-creation,%s,0x%x,%d,\"%s\"\n", tag,
+ reinterpret_cast<unsigned int>(code->address()),
+ CodeObjectSize(code), *str);
+ msg.WriteToLogFile();
#endif
}
@@ -599,14 +726,16 @@
String* source, int line) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_code) return;
- ScopedLock sl(mutex_);
+ LogMessageBuilder msg;
SmartPointer<char> str =
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
SmartPointer<char> sourcestr =
source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- fprintf(logfile_, "code-creation,%s,0x%x,%d,\"%s %s:%d\"\n", tag,
- reinterpret_cast<unsigned int>(code->address()),
- code->instruction_size(), *str, *sourcestr, line);
+ msg.Append("code-creation,%s,0x%x,%d,\"%s %s:%d\"\n", tag,
+ reinterpret_cast<unsigned int>(code->address()),
+ CodeObjectSize(code),
+ *str, *sourcestr, line);
+ msg.WriteToLogFile();
#endif
}
@@ -614,12 +743,12 @@
void Logger::CodeCreateEvent(const char* tag, Code* code, int args_count) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_code) return;
- ScopedLock sl(mutex_);
-
- fprintf(logfile_, "code-creation,%s,0x%x,%d,\"args_count: %d\"\n", tag,
- reinterpret_cast<unsigned int>(code->address()),
- code->instruction_size(),
- args_count);
+ LogMessageBuilder msg;
+ msg.Append("code-creation,%s,0x%x,%d,\"args_count: %d\"\n", tag,
+ reinterpret_cast<unsigned int>(code->address()),
+ CodeObjectSize(code),
+ args_count);
+ msg.WriteToLogFile();
#endif
}
@@ -627,11 +756,11 @@
void Logger::CodeAllocateEvent(Code* code, Assembler* assem) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_code) return;
- ScopedLock sl(mutex_);
-
- fprintf(logfile_, "code-allocate,0x%x,0x%x\n",
- reinterpret_cast<unsigned int>(code->address()),
- reinterpret_cast<unsigned int>(assem));
+ LogMessageBuilder msg;
+ msg.Append("code-allocate,0x%x,0x%x\n",
+ reinterpret_cast<unsigned int>(code->address()),
+ reinterpret_cast<unsigned int>(assem));
+ msg.WriteToLogFile();
#endif
}
@@ -639,10 +768,11 @@
void Logger::CodeMoveEvent(Address from, Address to) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_code) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "code-move,0x%x,0x%x\n",
- reinterpret_cast<unsigned int>(from),
- reinterpret_cast<unsigned int>(to));
+ LogMessageBuilder msg;
+ msg.Append("code-move,0x%x,0x%x\n",
+ reinterpret_cast<unsigned int>(from),
+ reinterpret_cast<unsigned int>(to));
+ msg.WriteToLogFile();
#endif
}
@@ -650,8 +780,9 @@
void Logger::CodeDeleteEvent(Address from) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_code) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "code-delete,0x%x\n", reinterpret_cast<unsigned
int>(from));
+ LogMessageBuilder msg;
+ msg.Append("code-delete,0x%x\n", reinterpret_cast<unsigned int>(from));
+ msg.WriteToLogFile();
#endif
}
@@ -661,12 +792,13 @@
const char* name) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_code) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "begin-code-region,0x%x,0x%x,0x%x,%s\n",
- reinterpret_cast<unsigned int>(region),
- reinterpret_cast<unsigned int>(masm),
- masm->pc_offset(),
- name);
+ LogMessageBuilder msg;
+ msg.Append("begin-code-region,0x%x,0x%x,0x%x,%s\n",
+ reinterpret_cast<unsigned int>(region),
+ reinterpret_cast<unsigned int>(masm),
+ masm->pc_offset(),
+ name);
+ msg.WriteToLogFile();
#endif
}
@@ -674,11 +806,12 @@
void Logger::EndCodeRegionEvent(CodeRegion* region, Assembler* masm) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_code) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "end-code-region,0x%x,0x%x,0x%x\n",
- reinterpret_cast<unsigned int>(region),
- reinterpret_cast<unsigned int>(masm),
- masm->pc_offset());
+ LogMessageBuilder msg;
+ msg.Append("end-code-region,0x%x,0x%x,0x%x\n",
+ reinterpret_cast<unsigned int>(region),
+ reinterpret_cast<unsigned int>(masm),
+ masm->pc_offset());
+ msg.WriteToLogFile();
#endif
}
@@ -686,16 +819,17 @@
void Logger::ResourceEvent(const char* name, const char* tag) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "%s,%s,", name, tag);
+ LogMessageBuilder msg;
+ msg.Append("%s,%s,", name, tag);
uint32_t sec, usec;
if (OS::GetUserTime(&sec, &usec) != -1) {
- fprintf(logfile_, "%d,%d,", sec, usec);
+ msg.Append("%d,%d,", sec, usec);
}
- fprintf(logfile_, "%.0f", OS::TimeCurrentMillis());
+ msg.Append("%.0f", OS::TimeCurrentMillis());
- fprintf(logfile_, "\n");
+ msg.Append('\n');
+ msg.WriteToLogFile();
#endif
}
@@ -703,15 +837,19 @@
void Logger::SuspectReadEvent(String* name, Object* obj) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_suspect) return;
+ LogMessageBuilder msg;
String* class_name = obj->IsJSObject()
? JSObject::cast(obj)->class_name()
: Heap::empty_string();
ScopedLock sl(mutex_);
- fprintf(logfile_, "suspect-read,");
- class_name->PrintOn(logfile_);
- fprintf(logfile_, ",\"");
- name->PrintOn(logfile_);
- fprintf(logfile_, "\"\n");
+ msg.Append("suspect-read,");
+ msg.Append(class_name);
+ msg.Append(',');
+ msg.Append('"');
+ msg.Append(name);
+ msg.Append('"');
+ msg.Append('\n');
+ msg.WriteToLogFile();
#endif
}
@@ -719,8 +857,9 @@
void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_gc) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "heap-sample-begin,\"%s\",\"%s\"\n", space, kind);
+ LogMessageBuilder msg;
+ msg.Append("heap-sample-begin,\"%s\",\"%s\"\n", space, kind);
+ msg.WriteToLogFile();
#endif
}
@@ -728,8 +867,9 @@
void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_gc) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "heap-sample-end,\"%s\",\"%s\"\n", space, kind);
+ LogMessageBuilder msg;
+ msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind);
+ msg.WriteToLogFile();
#endif
}
@@ -737,8 +877,9 @@
void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log_gc) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "heap-sample-item,%s,%d,%d\n", type, number, bytes);
+ LogMessageBuilder msg;
+ msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes);
+ msg.WriteToLogFile();
#endif
}
@@ -746,8 +887,9 @@
void Logger::DebugTag(const char* call_site_tag) {
#ifdef ENABLE_LOGGING_AND_PROFILING
if (logfile_ == NULL || !FLAG_log) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "debug-tag,%s\n", call_site_tag);
+ LogMessageBuilder msg;
+ msg.Append("debug-tag,%s\n", call_site_tag);
+ msg.WriteToLogFile();
#endif
}
@@ -760,13 +902,13 @@
s.AddCharacter(static_cast<char>(parameter[i]));
}
char* parameter_string = s.Finalize();
- ScopedLock sl(mutex_);
- fprintf(logfile_,
- "debug-queue-event,%s,%15.3f,%s\n",
- event_type,
- OS::TimeCurrentMillis(),
- parameter_string);
+ LogMessageBuilder msg;
+ msg.Append("debug-queue-event,%s,%15.3f,%s\n",
+ event_type,
+ OS::TimeCurrentMillis(),
+ parameter_string);
DeleteArray(parameter_string);
+ msg.WriteToLogFile();
#endif
}
@@ -774,11 +916,19 @@
#ifdef ENABLE_LOGGING_AND_PROFILING
void Logger::TickEvent(TickSample* sample, bool overflow) {
if (logfile_ == NULL || !FLAG_prof) return;
- ScopedLock sl(mutex_);
- fprintf(logfile_, "tick,0x%x,0x%x,%d", sample->pc, sample->sp,
- static_cast<int>(sample->state));
- if (overflow) fprintf(logfile_, ",overflow");
- fprintf(logfile_, "\n");
+ LogMessageBuilder msg;
+ msg.Append("tick,0x%x,0x%x,%d", sample->pc, sample->sp,
+ static_cast<int>(sample->state));
+ if (overflow) {
+ msg.Append(",overflow");
+ }
+ if (*(sample->stack)) {
+ for (size_t i = 0; sample->stack[i]; ++i) {
+ msg.Append(",0x%x", reinterpret_cast<unsigned
int>(sample->stack[i]));
+ }
+ }
+ msg.Append('\n');
+ msg.WriteToLogFile();
}
@@ -802,6 +952,7 @@
#ifdef ENABLE_LOGGING_AND_PROFILING
// --log-all enables all the log flags.
if (FLAG_log_all) {
+ FLAG_log_runtime = true;
FLAG_log_api = true;
FLAG_log_code = true;
FLAG_log_gc = true;
@@ -813,8 +964,8 @@
// --prof implies --log-code.
if (FLAG_prof) FLAG_log_code = true;
- bool open_log_file = FLAG_log || FLAG_log_api || FLAG_log_code
- || FLAG_log_gc || FLAG_log_handles || FLAG_log_suspect
+ bool open_log_file = FLAG_log || FLAG_log_runtime || FLAG_log_api
+ || FLAG_log_code || FLAG_log_gc || FLAG_log_handles ||
FLAG_log_suspect
|| FLAG_log_regexp || FLAG_log_state_changes;
// If we're logging anything, we need to open the log file.
@@ -860,12 +1011,16 @@
} else {
logfile_ = OS::FOpen(FLAG_logfile, "w");
}
+ message_buffer_ = NewArray<char>(kMessageBufferSize);
mutex_ = OS::CreateMutex();
}
current_state_ = new VMState(OTHER);
- ticker_ = new Ticker(10);
+ // as log is initialized early with V8, we can assume that JS execution
+ // frames can never reach this point on stack
+ int stack_var;
+ ticker_ = new Ticker(10, reinterpret_cast<unsigned int>(&stack_var));
if (FLAG_sliding_state_window && sliding_state_window_ == NULL) {
sliding_state_window_ = new SlidingStateWindow();
@@ -906,6 +1061,7 @@
logfile_ = NULL;
delete mutex_;
mutex_ = NULL;
+ DeleteArray(message_buffer_);
}
#endif
}
Modified: branches/experimental/toiger/src/log.h
==============================================================================
--- branches/experimental/toiger/src/log.h (original)
+++ branches/experimental/toiger/src/log.h Thu Feb 19 05:07:13 2009
@@ -69,6 +69,7 @@
class Profiler;
class Semaphore;
class SlidingStateWindow;
+class LogMessageBuilder;
#undef LOG
#ifdef ENABLE_LOGGING_AND_PROFILING
@@ -214,11 +215,13 @@
private:
+ // Calculate the size of the code object to report for log events. This
takes
+ // the layout of the code object into account.
+ static int CodeObjectSize(Code* code);
+
// Emits the source code of a regexp. Used by regexp events.
static void LogRegExpSource(Handle<JSRegExp> regexp);
- static void LogString(Handle<String> str, bool show_impl_info);
-
// Emits a profiler tick event. Used by the profiler thread.
static void TickEvent(TickSample* sample, bool overflow);
@@ -227,8 +230,15 @@
// Logs a StringEvent regardless of whether FLAG_log is true.
static void UncheckedStringEvent(const char* name, const char* value);
- // When logging is active, logfile_ refers the file
- // events are written to.
+ // Size of buffer used for formatting log messages.
+ static const int kMessageBufferSize = 256;
+
+ // Buffer used for formatting log messages. This is a singleton buffer
and
+ // mutex_ should be acquired before using it.
+ static char* message_buffer_;
+
+ // When logging is active, logfile_ refers the file events are written
to.
+ // mutex_ should be acquired before using logfile_.
static FILE* logfile_;
// The sampler used by the profiler and the sliding state window.
@@ -240,7 +250,7 @@
static Profiler* profiler_;
// mutex_ is a Mutex used for enforcing exclusive
- // access to the log file.
+ // access to the formatting buffer and the log file.
static Mutex* mutex_;
// A stack of VM states.
@@ -252,6 +262,7 @@
// Internal implementation classes with access to
// private members.
+ friend class LogMessageBuilder;
friend class EventLog;
friend class TimeLog;
friend class Profiler;
Modified: branches/experimental/toiger/src/platform-freebsd.cc
==============================================================================
--- branches/experimental/toiger/src/platform-freebsd.cc (original)
+++ branches/experimental/toiger/src/platform-freebsd.cc Thu Feb 19
05:07:13 2009
@@ -634,9 +634,11 @@
#if defined (__arm__) || defined(__thumb__)
sample.pc = mcontext.mc_r15;
sample.sp = mcontext.mc_r13;
+ sample.fp = mcontext.mc_r11;
#else
sample.pc = mcontext.mc_eip;
sample.sp = mcontext.mc_esp;
+ sample.fp = mcontext.mc_ebp;
#endif
}
Modified: branches/experimental/toiger/src/platform-linux.cc
==============================================================================
--- branches/experimental/toiger/src/platform-linux.cc (original)
+++ branches/experimental/toiger/src/platform-linux.cc Thu Feb 19 05:07:13
2009
@@ -617,9 +617,11 @@
#if defined (__arm__) || defined(__thumb__)
sample.pc = mcontext.gregs[R15];
sample.sp = mcontext.gregs[R13];
+ sample.fp = mcontext.gregs[R11];
#else
sample.pc = mcontext.gregs[REG_EIP];
sample.sp = mcontext.gregs[REG_ESP];
+ sample.fp = mcontext.gregs[REG_EBP];
#endif
}
Modified: branches/experimental/toiger/src/platform-macos.cc
==============================================================================
--- branches/experimental/toiger/src/platform-macos.cc (original)
+++ branches/experimental/toiger/src/platform-macos.cc Thu Feb 19 05:07:13
2009
@@ -583,9 +583,11 @@
#if __DARWIN_UNIX03
sample.pc = mcontext->__ss.__eip;
sample.sp = mcontext->__ss.__esp;
+ sample.fp = mcontext->__ss.__ebp;
#else // !__DARWIN_UNIX03
sample.pc = mcontext->ss.eip;
sample.sp = mcontext->ss.esp;
+ sample.fp = mcontext->ss.ebp;
#endif // __DARWIN_UNIX03
}
Modified: branches/experimental/toiger/src/platform-win32.cc
==============================================================================
--- branches/experimental/toiger/src/platform-win32.cc (original)
+++ branches/experimental/toiger/src/platform-win32.cc Thu Feb 19 05:07:13
2009
@@ -1585,6 +1585,7 @@
// Invoke tick handler with program counter and stack pointer.
sample.pc = context.Eip;
sample.sp = context.Esp;
+ sample.fp = context.Ebp;
}
// We always sample the VM state.
Modified: branches/experimental/toiger/src/platform.h
==============================================================================
--- branches/experimental/toiger/src/platform.h (original)
+++ branches/experimental/toiger/src/platform.h Thu Feb 19 05:07:13 2009
@@ -422,10 +422,29 @@
// TickSample captures the information collected for each sample.
class TickSample {
public:
- TickSample() : pc(0), sp(0), state(OTHER) {}
+ TickSample() : pc(0), sp(0), fp(0), state(OTHER) {}
unsigned int pc; // Instruction pointer.
unsigned int sp; // Stack pointer.
+ unsigned int fp; // Frame pointer.
StateTag state; // The state of the VM.
+ SmartPointer<Address> stack; // Call stack, null-terminated.
+
+ inline TickSample& operator=(const TickSample& rhs) {
+ if (this == &rhs) return *this;
+ pc = rhs.pc;
+ sp = rhs.sp;
+ fp = rhs.fp;
+ state = rhs.state;
+ DeleteArray(stack.Detach());
+ stack = rhs.stack;
+ return *this;
+ }
+
+ inline void InitStack(int depth) {
+ stack = SmartPointer<Address>(NewArray<Address>(depth + 1));
+ // null-terminate
+ stack[depth] = 0;
+ }
};
class Sampler {
Modified: branches/experimental/toiger/src/runtime.cc
==============================================================================
--- branches/experimental/toiger/src/runtime.cc (original)
+++ branches/experimental/toiger/src/runtime.cc Thu Feb 19 05:07:13 2009
@@ -4625,7 +4625,7 @@
reinterpret_cast<AccessorDescriptor*>(
Proxy::cast(structure)->proxy());
value = (callback->getter)(receiver, callback->data);
- if (value->IsFailure()) {
+ if (value->IsException()) {
value = Top::pending_exception();
Top::clear_pending_exception();
if (caught_exception != NULL) {
@@ -4705,15 +4705,17 @@
if (result.IsProperty()) {
bool caught_exception = false;
- Handle<Object> value(DebugLookupResultValue(*obj, &result,
- &caught_exception));
+ Object* value = DebugLookupResultValue(*obj, &result,
+ &caught_exception);
+ if (value->IsFailure()) return value;
+ Handle<Object> value_handle(value);
// If the callback object is a fixed array then it contains JavaScript
// getter and/or setter.
bool hasJavaScriptAccessors = result.type() == CALLBACKS &&
result.GetCallbackObject()->IsFixedArray();
Handle<FixedArray> details =
Factory::NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
- details->set(0, *value);
+ details->set(0, *value_handle);
details->set(1, result.GetPropertyDetails().AsSmi());
if (hasJavaScriptAccessors) {
details->set(2,
@@ -6035,9 +6037,9 @@
static Object* Runtime_Log(Arguments args) {
ASSERT(args.length() == 2);
- String* format = String::cast(args[0]);
+ CONVERT_CHECKED(String, format, args[0]);
+ CONVERT_CHECKED(JSArray, elms, args[1]);
Vector<const char> chars = format->ToAsciiVector();
- JSArray* elms = JSArray::cast(args[1]);
Logger::LogRuntime(chars, elms);
return Heap::undefined_value();
}
Modified: branches/experimental/toiger/tools/linux-tick-processor.py
==============================================================================
--- branches/experimental/toiger/tools/linux-tick-processor.py (original)
+++ branches/experimental/toiger/tools/linux-tick-processor.py Thu Feb 19
05:07:13 2009
@@ -60,9 +60,10 @@
def Main():
# parse command line options
+ ignore_unknown = False
state = None;
try:
- opts, args = getopt.getopt(sys.argv[1:], "jgco",
["js", "gc", "compiler", "other"])
+ opts, args = getopt.getopt(sys.argv[1:], "jgco",
["js", "gc", "compiler", "other", "ignore-unknown"])
except getopt.GetoptError:
usage()
# process options.
@@ -75,11 +76,13 @@
state = 2
if key in ("-o", "--other"):
state = 3
+ if key in ("--ignore-unknown"):
+ ignore_unknown = True
# do the processing.
if len(args) != 1:
Usage();
tick_processor = LinuxTickProcessor()
- tick_processor.ProcessLogfile(args[0], state)
+ tick_processor.ProcessLogfile(args[0], state, ignore_unknown)
tick_processor.PrintResults()
if __name__ == '__main__':
Modified: branches/experimental/toiger/tools/tickprocessor.py
==============================================================================
--- branches/experimental/toiger/tools/tickprocessor.py (original)
+++ branches/experimental/toiger/tools/tickprocessor.py Thu Feb 19 05:07:13
2009
@@ -26,6 +26,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import csv, splaytree, sys
+from operator import itemgetter
class CodeEntry(object):
@@ -34,9 +35,14 @@
self.start_addr = start_addr
self.tick_count = 0
self.name = name
+ self.stacks = {}
- def Tick(self, pc):
+ def Tick(self, pc, stack):
self.tick_count += 1
+ if len(stack) > 0:
+ stack.insert(0, self.ToString())
+ stack_key = tuple(stack)
+ self.stacks[stack_key] = self.stacks.setdefault(stack_key, 0) + 1
def RegionTicks(self):
return None
@@ -69,8 +75,8 @@
self.assembler = assembler
self.region_ticks = None
- def Tick(self, pc):
- super(JSCodeEntry, self).Tick(pc)
+ def Tick(self, pc, stack):
+ super(JSCodeEntry, self).Tick(pc, stack)
if not pc is None:
offset = pc - self.start_addr
seen = []
@@ -150,10 +156,14 @@
self.number_of_library_ticks = 0
self.unaccounted_number_of_ticks = 0
self.excluded_number_of_ticks = 0
+ # Flag indicating whether to ignore unaccounted ticks in the report
+ self.ignore_unknown = False
- def ProcessLogfile(self, filename, included_state = None):
+ def ProcessLogfile(self, filename, included_state = None, ignore_unknown
= False):
self.log_file = filename
self.included_state = included_state
+ self.ignore_unknown = ignore_unknown
+
try:
logfile = open(filename, 'rb')
except IOError:
@@ -162,7 +172,7 @@
logreader = csv.reader(logfile)
for row in logreader:
if row[0] == 'tick':
- self.ProcessTick(int(row[1], 16), int(row[2], 16), int(row[3]))
+ self.ProcessTick(int(row[1], 16), int(row[2], 16), int(row[3]),
row[4:])
elif row[0] == 'code-creation':
self.ProcessCodeCreation(row[1], int(row[2], 16), int(row[3]),
row[4])
elif row[0] == 'code-move':
@@ -237,25 +247,41 @@
def IncludeTick(self, pc, sp, state):
return (self.included_state is None) or (self.included_state == state)
- def ProcessTick(self, pc, sp, state):
- if not self.IncludeTick(pc, sp, state):
- self.excluded_number_of_ticks += 1;
- return
- self.total_number_of_ticks += 1
+ def FindEntry(self, pc):
page = pc >> 12
if page in self.vm_extent:
- entry = self.cpp_entries.FindGreatestsLessThan(pc).value
- if entry.IsSharedLibraryEntry():
- self.number_of_library_ticks += 1
- entry.Tick(None)
- return
+ entry = self.cpp_entries.FindGreatestsLessThan(pc)
+ if entry != None:
+ return entry.value
+ else:
+ return entry
max = self.js_entries.FindMax()
min = self.js_entries.FindMin()
- if max != None and pc < max.key and pc > min.key:
- code_obj = self.js_entries.FindGreatestsLessThan(pc).value
- code_obj.Tick(pc)
+ if max != None and pc < (max.key + max.value.size) and pc > min.key:
+ return self.js_entries.FindGreatestsLessThan(pc).value
+ return None
+
+ def ProcessStack(self, stack):
+ result = []
+ for frame in stack:
+ if frame.startswith('0x'):
+ entry = self.FindEntry(int(frame, 16))
+ if entry != None:
+ result.append(entry.ToString())
+ return result
+
+ def ProcessTick(self, pc, sp, state, stack):
+ if not self.IncludeTick(pc, sp, state):
+ self.excluded_number_of_ticks += 1;
+ return
+ self.total_number_of_ticks += 1
+ entry = self.FindEntry(pc)
+ if entry == None:
+ self.unaccounted_number_of_ticks += 1
return
- self.unaccounted_number_of_ticks += 1
+ if entry.IsSharedLibraryEntry():
+ self.number_of_library_ticks += 1
+ entry.Tick(pc, self.ProcessStack(stack))
def PrintResults(self):
print('Statistical profiling result from %s, (%d ticks, %d
unaccounted, %d excluded).' %
@@ -267,6 +293,13 @@
js_entries = self.js_entries.ExportValueList()
js_entries.extend(self.deleted_code)
cpp_entries = self.cpp_entries.ExportValueList()
+ # Print the unknown ticks percentage if they are not ignored.
+ if not self.ignore_unknown and self.unaccounted_number_of_ticks > 0:
+ self.PrintHeader('Unknown')
+ unknown_percentage = self.unaccounted_number_of_ticks * 100.0 /
self.total_number_of_ticks
+ print(' %(total)5.1f%%' % {
+ 'total' : unknown_percentage,
+ })
# Print the library ticks.
self.PrintHeader('Shared libraries')
self.PrintEntries(cpp_entries, lambda e:e.IsSharedLibraryEntry())
@@ -276,13 +309,23 @@
# Print the C++ ticks.
self.PrintHeader('C++')
self.PrintEntries(cpp_entries, lambda e:not e.IsSharedLibraryEntry())
+ # Print call profile.
+ print('\n [Call profile]:')
+ print(' total call path')
+ js_entries.extend(cpp_entries)
+ self.PrintCallProfile(js_entries)
def PrintHeader(self, header_title):
print('\n [%s]:' % header_title)
print(' total nonlib name')
def PrintEntries(self, entries, condition):
- number_of_accounted_ticks = self.total_number_of_ticks -
self.unaccounted_number_of_ticks
+ # If ignoring unaccounted ticks don't include these in percentage
+ # calculations
+ number_of_accounted_ticks = self.total_number_of_ticks
+ if self.ignore_unknown:
+ number_of_accounted_ticks -= self.unaccounted_number_of_ticks
+
number_of_non_library_ticks = number_of_accounted_ticks -
self.number_of_library_ticks
entries.sort(key=lambda e:e.tick_count, reverse=True)
for entry in entries:
@@ -308,6 +351,22 @@
'accum' : ticks[0] * 100.0 / entry.tick_count,
'name': name
})
+
+ def PrintCallProfile(self, entries):
+ all_stacks = {}
+ total_stacks = 0
+ for entry in entries:
+ all_stacks.update(entry.stacks)
+ for count in entry.stacks.itervalues():
+ total_stacks += count
+ all_stacks_items = all_stacks.items();
+ all_stacks_items.sort(key = itemgetter(1), reverse=True)
+ for stack, count in all_stacks_items:
+ total_percentage = count * 100.0 / total_stacks
+ print(' %(total)5.1f%% %(call_path)s' % {
+ 'total' : total_percentage,
+ 'call_path' : stack[0] + ' <- ' + stack[1]
+ })
if __name__ == '__main__':
sys.exit('You probably want to run windows-tick-processor.py or
linux-tick-processor.py.')
Modified: branches/experimental/toiger/tools/windows-tick-processor.py
==============================================================================
--- branches/experimental/toiger/tools/windows-tick-processor.py
(original)
+++ branches/experimental/toiger/tools/windows-tick-processor.py Thu Feb
19
05:07:13 2009
@@ -113,9 +113,10 @@
def Main():
# parse command line options
+ ignore_unknown = False
state = None;
try:
- opts, args = getopt.getopt(sys.argv[1:], "jgco",
["js", "gc", "compiler", "other"])
+ opts, args = getopt.getopt(sys.argv[1:], "jgco",
["js", "gc", "compiler", "other", "ignore-unknown"])
except getopt.GetoptError:
usage()
# process options.
@@ -128,12 +129,14 @@
state = 2
if key in ("-o", "--other"):
state = 3
+ if key in ("--ignore-unknown"):
+ ignore_unknown = True
# do the processing.
if len(args) != 2:
Usage();
tickprocessor = WindowsTickProcessor()
tickprocessor.ParseMapFile(args[0])
- tickprocessor.ProcessLogfile(args[1], state)
+ tickprocessor.ProcessLogfile(args[1], state, ignore_unknown)
tickprocessor.PrintResults()
if __name__ == '__main__':
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---