Introduce internal Log class that handles writing log messages, enable logging to memory buffer.

This will enable reading profiler log in Chrome. The current implementation of memory buffer is trivial (fixed size buffer, no memory recycling) but enough to start end-to-end DevTools Profiler implementation. Later it will be enhanced.

Review URL: http://codereview.chromium.org/108011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1870 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e3762851
...@@ -2079,6 +2079,24 @@ class V8EXPORT V8 { ...@@ -2079,6 +2079,24 @@ class V8EXPORT V8 {
*/ */
static void ResumeProfiler(); static void ResumeProfiler();
/**
* If logging is performed into a memory buffer (via --logfile=*), allows to
* retrieve previously written messages. This can be used for retrieving
* profiler log data in the application. This function is thread-safe.
*
* Caller provides a destination buffer that must exist during GetLogLines
* call. Only whole log lines are copied into the buffer.
*
* \param from_pos specified a point in a buffer to read from, 0 is the
* beginning of a buffer. It is assumed that caller updates its current
* position using returned size value from the previous call.
* \param dest_buf destination buffer for log data.
* \param max_size size of the destination buffer.
* \returns actual size of log data copied into buffer.
*/
static int GetLogLines(int from_pos, char* dest_buf, int max_size);
/** /**
* Releases any resources used by v8 and stops any utility threads * Releases any resources used by v8 and stops any utility threads
* that may be running. Note that disposing v8 is permanent, it * that may be running. Note that disposing v8 is permanent, it
......
...@@ -3112,6 +3112,11 @@ void V8::ResumeProfiler() { ...@@ -3112,6 +3112,11 @@ void V8::ResumeProfiler() {
#endif #endif
} }
int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
#ifdef ENABLE_LOGGING_AND_PROFILING
return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
#endif
}
String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) { String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
EnsureInitialized("v8::String::Utf8Value::Utf8Value()"); EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
......
This diff is collapsed.
...@@ -103,10 +103,10 @@ class VMState BASE_EMBEDDED { ...@@ -103,10 +103,10 @@ class VMState BASE_EMBEDDED {
class Logger { class Logger {
public: public:
// Opens the file for logging if the right flags are set. // Acquires resources for logging if the right flags are set.
static bool Setup(); static bool Setup();
// Closes file opened in Setup. // Frees resources acquired in Setup.
static void TearDown(); static void TearDown();
// Enable the computation of a sliding window of states. // Enable the computation of a sliding window of states.
...@@ -201,7 +201,7 @@ class Logger { ...@@ -201,7 +201,7 @@ class Logger {
return current_state_ ? current_state_->state() : OTHER; return current_state_ ? current_state_->state() : OTHER;
} }
static bool is_enabled() { return logfile_ != NULL; } static bool is_enabled();
// Pause/Resume collection of profiling data. // Pause/Resume collection of profiling data.
// When data collection is paused, Tick events are discarded until // When data collection is paused, Tick events are discarded until
...@@ -210,6 +210,10 @@ class Logger { ...@@ -210,6 +210,10 @@ class Logger {
static void PauseProfiler(); static void PauseProfiler();
static void ResumeProfiler(); static void ResumeProfiler();
// If logging is performed into a memory buffer, allows to
// retrieve previously written messages. See v8.h.
static int GetLogLines(int from_pos, char* dest_buf, int max_size);
private: private:
// Emits the source code of a regexp. Used by regexp events. // Emits the source code of a regexp. Used by regexp events.
...@@ -223,17 +227,6 @@ class Logger { ...@@ -223,17 +227,6 @@ class Logger {
// Logs a StringEvent regardless of whether FLAG_log is true. // Logs a StringEvent regardless of whether FLAG_log is true.
static void UncheckedStringEvent(const char* name, const char* value); static void UncheckedStringEvent(const char* name, const char* value);
// Size of buffer used for formatting log messages.
static const int kMessageBufferSize = 2048;
// 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. // The sampler used by the profiler and the sliding state window.
static Ticker* ticker_; static Ticker* ticker_;
...@@ -242,10 +235,6 @@ class Logger { ...@@ -242,10 +235,6 @@ class Logger {
// of samples. // of samples.
static Profiler* profiler_; static Profiler* profiler_;
// mutex_ is a Mutex used for enforcing exclusive
// access to the formatting buffer and the log file.
static Mutex* mutex_;
// A stack of VM states. // A stack of VM states.
static VMState* current_state_; static VMState* current_state_;
...@@ -258,7 +247,6 @@ class Logger { ...@@ -258,7 +247,6 @@ class Logger {
// Internal implementation classes with access to // Internal implementation classes with access to
// private members. // private members.
friend class LogMessageBuilder;
friend class EventLog; friend class EventLog;
friend class TimeLog; friend class TimeLog;
friend class Profiler; friend class Profiler;
......
...@@ -47,6 +47,7 @@ SOURCES = { ...@@ -47,6 +47,7 @@ SOURCES = {
'test-heap.cc', 'test-heap.cc',
'test-list.cc', 'test-list.cc',
'test-lock.cc', 'test-lock.cc',
'test-log.cc',
'test-mark-compact.cc', 'test-mark-compact.cc',
'test-regexp.cc', 'test-regexp.cc',
'test-serialize.cc', 'test-serialize.cc',
......
// Copyright 2006-2009 the V8 project authors. All rights reserved.
//
// Tests of logging functions from log.h
#ifdef ENABLE_LOGGING_AND_PROFILING
#include "v8.h"
#include "log.h"
#include "cctest.h"
using v8::internal::Logger;
static void SetUp() {
// Log to memory buffer.
v8::internal::FLAG_logfile = "*";
v8::internal::FLAG_log = true;
Logger::Setup();
}
static void TearDown() {
Logger::TearDown();
}
TEST(EmptyLog) {
SetUp();
CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0));
CHECK_EQ(0, Logger::GetLogLines(100, NULL, 0));
CHECK_EQ(0, Logger::GetLogLines(0, NULL, 100));
CHECK_EQ(0, Logger::GetLogLines(100, NULL, 100));
TearDown();
}
TEST(GetMessages) {
SetUp();
Logger::StringEvent("aaa", "bbb");
Logger::StringEvent("cccc", "dddd");
CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0));
char log_lines[100];
memset(log_lines, 0, sizeof(log_lines));
// Requesting data size which is smaller than first log message length.
CHECK_EQ(0, Logger::GetLogLines(0, log_lines, 3));
// See Logger::StringEvent.
const char* line_1 = "aaa,\"bbb\"\n";
const int line_1_len = strlen(line_1);
// Still smaller than log message length.
CHECK_EQ(0, Logger::GetLogLines(0, log_lines, line_1_len - 1));
// The exact size.
CHECK_EQ(line_1_len, Logger::GetLogLines(0, log_lines, line_1_len));
CHECK_EQ(line_1, log_lines);
memset(log_lines, 0, sizeof(log_lines));
// A bit more than the first line length.
CHECK_EQ(line_1_len, Logger::GetLogLines(0, log_lines, line_1_len + 3));
CHECK_EQ(line_1, log_lines);
memset(log_lines, 0, sizeof(log_lines));
const char* line_2 = "cccc,\"dddd\"\n";
const int line_2_len = strlen(line_2);
// Now start with line_2 beginning.
CHECK_EQ(0, Logger::GetLogLines(line_1_len, log_lines, 0));
CHECK_EQ(0, Logger::GetLogLines(line_1_len, log_lines, 3));
CHECK_EQ(0, Logger::GetLogLines(line_1_len, log_lines, line_2_len - 1));
CHECK_EQ(line_2_len, Logger::GetLogLines(line_1_len, log_lines, line_2_len));
CHECK_EQ(line_2, log_lines);
memset(log_lines, 0, sizeof(log_lines));
CHECK_EQ(line_2_len,
Logger::GetLogLines(line_1_len, log_lines, line_2_len + 3));
CHECK_EQ(line_2, log_lines);
memset(log_lines, 0, sizeof(log_lines));
// Now get entire buffer contents.
const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n";
const int all_lines_len = strlen(all_lines);
CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len));
CHECK_EQ(all_lines, log_lines);
memset(log_lines, 0, sizeof(log_lines));
CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len + 3));
CHECK_EQ(all_lines, log_lines);
memset(log_lines, 0, sizeof(log_lines));
TearDown();
}
TEST(BeyondWritePosition) {
SetUp();
Logger::StringEvent("aaa", "bbb");
Logger::StringEvent("cccc", "dddd");
// See Logger::StringEvent.
const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n";
const int all_lines_len = strlen(all_lines);
CHECK_EQ(0, Logger::GetLogLines(all_lines_len, NULL, 1));
CHECK_EQ(0, Logger::GetLogLines(all_lines_len, NULL, 100));
CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 1, NULL, 1));
CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 1, NULL, 100));
CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 100, NULL, 1));
CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 100, NULL, 100));
CHECK_EQ(0, Logger::GetLogLines(10 * 1024 * 1024, NULL, 1));
CHECK_EQ(0, Logger::GetLogLines(10 * 1024 * 1024, NULL, 100));
TearDown();
}
#endif // ENABLE_LOGGING_AND_PROFILING
...@@ -201,6 +201,10 @@ ...@@ -201,6 +201,10 @@
RelativePath="..\..\test\cctest\test-lock.cc" RelativePath="..\..\test\cctest\test-lock.cc"
> >
</File> </File>
<File
RelativePath="..\..\test\cctest\test-log.cc"
>
</File>
<File <File
RelativePath="..\..\test\cctest\test-log-ia32.cc" RelativePath="..\..\test\cctest\test-log-ia32.cc"
> >
......
...@@ -195,6 +195,10 @@ ...@@ -195,6 +195,10 @@
RelativePath="..\..\test\cctest\test-lock.cc" RelativePath="..\..\test\cctest\test-lock.cc"
> >
</File> </File>
<File
RelativePath="..\..\test\cctest\test-log.cc"
>
</File>
<File <File
RelativePath="..\..\test\cctest\test-mark-compact.cc" RelativePath="..\..\test\cctest\test-mark-compact.cc"
> >
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment