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
......@@ -1126,9 +1126,9 @@ class V8EXPORT Object : public Value {
/**
* Returns the identity hash for this object. The current implemenation uses
* a hidden property on the object to store the identity hash.
* a hidden property on the object to store the identity hash.
*
* The return value will never be 0. Also, it is not guaranteed to be
* The return value will never be 0. Also, it is not guaranteed to be
* unique.
*/
int GetIdentityHash();
......@@ -2079,6 +2079,24 @@ class V8EXPORT V8 {
*/
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
* that may be running. Note that disposing v8 is permanent, it
......
......@@ -3112,6 +3112,11 @@ void V8::ResumeProfiler() {
#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) {
EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
......
This diff is collapsed.
......@@ -103,10 +103,10 @@ class VMState BASE_EMBEDDED {
class Logger {
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();
// Closes file opened in Setup.
// Frees resources acquired in Setup.
static void TearDown();
// Enable the computation of a sliding window of states.
......@@ -201,7 +201,7 @@ class Logger {
return current_state_ ? current_state_->state() : OTHER;
}
static bool is_enabled() { return logfile_ != NULL; }
static bool is_enabled();
// Pause/Resume collection of profiling data.
// When data collection is paused, Tick events are discarded until
......@@ -210,6 +210,10 @@ class Logger {
static void PauseProfiler();
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:
// Emits the source code of a regexp. Used by regexp events.
......@@ -223,17 +227,6 @@ class Logger {
// Logs a StringEvent regardless of whether FLAG_log is true.
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.
static Ticker* ticker_;
......@@ -242,10 +235,6 @@ class Logger {
// of samples.
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.
static VMState* current_state_;
......@@ -258,7 +247,6 @@ class Logger {
// Internal implementation classes with access to
// private members.
friend class LogMessageBuilder;
friend class EventLog;
friend class TimeLog;
friend class Profiler;
......
......@@ -47,6 +47,7 @@ SOURCES = {
'test-heap.cc',
'test-list.cc',
'test-lock.cc',
'test-log.cc',
'test-mark-compact.cc',
'test-regexp.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 @@
RelativePath="..\..\test\cctest\test-lock.cc"
>
</File>
<File
RelativePath="..\..\test\cctest\test-log.cc"
>
</File>
<File
RelativePath="..\..\test\cctest\test-log-ia32.cc"
>
......
......@@ -195,6 +195,10 @@
RelativePath="..\..\test\cctest\test-lock.cc"
>
</File>
<File
RelativePath="..\..\test\cctest\test-log.cc"
>
</File>
<File
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