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
-~----------~----~----~----~------~----~------~--~---

Reply via email to