Index: src/log.cc |
diff --git a/src/log.cc b/src/log.cc |
index 59018a18a0ae947e537986f9218f74874f3ab73f..e149fdb17a89ba80071bf76ee238df3e1159a7fc 100644 |
--- a/src/log.cc |
+++ b/src/log.cc |
@@ -31,6 +31,7 @@ |
#include "bootstrapper.h" |
#include "log.h" |
+#include "log-utils.h" |
#include "macro-assembler.h" |
#include "platform.h" |
#include "serialize.h" |
@@ -287,304 +288,6 @@ void Profiler::Run() { |
} |
-#ifdef ENABLE_LOGGING_AND_PROFILING |
- |
-// Functions and data for performing output of log messages. |
-class Log : public AllStatic { |
- public: |
- // Opens stdout for logging. |
- static void OpenStdout(); |
- |
- // Opens file for logging. |
- static void OpenFile(const char* name); |
- |
- // Opens memory buffer for logging. |
- static void OpenMemoryBuffer(); |
- |
- // Frees all resources acquired in Open... functions. |
- static void Close(); |
- |
- // See description in include/v8.h. |
- static int GetLogLines(int from_pos, char* dest_buf, int max_size); |
- |
- // Returns whether logging is enabled. |
- static bool IsEnabled() { |
- return output_handle_ != NULL || output_buffer_ != NULL; |
- } |
- |
- private: |
- typedef int (*WritePtr)(const char* msg, int length); |
- |
- // Initialization function called from Open... functions. |
- static void Init(); |
- |
- // Write functions assume that mutex_ is acquired by the caller. |
- static WritePtr Write; |
- |
- // Implementation of writing to a log file. |
- static int WriteToFile(const char* msg, int length) { |
- ASSERT(output_handle_ != NULL); |
- int rv = fwrite(msg, 1, length, output_handle_); |
- ASSERT(length == rv); |
- return rv; |
- } |
- |
- // Implementation of writing to a memory buffer. |
- static int WriteToMemory(const char* msg, int length) { |
- ASSERT(output_buffer_ != NULL); |
- ASSERT(output_buffer_write_pos_ >= output_buffer_); |
- if (output_buffer_write_pos_ + length |
- <= output_buffer_ + kOutputBufferSize) { |
- memcpy(output_buffer_write_pos_, msg, length); |
- output_buffer_write_pos_ += length; |
- return length; |
- } else { |
- // Memory buffer is full, ignore write. |
- return 0; |
- } |
- } |
- |
- // When logging is active, either output_handle_ or output_buffer_ is used |
- // to store a pointer to log destination. If logging was opened via OpenStdout |
- // or OpenFile, then output_handle_ is used. If logging was opened |
- // via OpenMemoryBuffer, then output_buffer_ is used. |
- // mutex_ should be acquired before using output_handle_ or output_buffer_. |
- static FILE* output_handle_; |
- |
- static char* output_buffer_; |
- |
- // mutex_ is a Mutex used for enforcing exclusive |
- // access to the formatting buffer and the log file or log memory buffer. |
- static Mutex* mutex_; |
- |
- // Size of buffer used for memory logging. |
- static const int kOutputBufferSize = 2 * 1024 * 1024; |
- |
- // Writing position in a memory buffer. |
- static char* output_buffer_write_pos_; |
- |
- // 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_; |
- |
- friend class LogMessageBuilder; |
-}; |
- |
- |
-Log::WritePtr Log::Write = NULL; |
-FILE* Log::output_handle_ = NULL; |
-char* Log::output_buffer_ = NULL; |
-Mutex* Log::mutex_ = NULL; |
-char* Log::output_buffer_write_pos_ = NULL; |
-char* Log::message_buffer_ = NULL; |
- |
- |
-void Log::Init() { |
- mutex_ = OS::CreateMutex(); |
- message_buffer_ = NewArray<char>(kMessageBufferSize); |
-} |
- |
- |
-void Log::OpenStdout() { |
- ASSERT(!IsEnabled()); |
- output_handle_ = stdout; |
- Write = WriteToFile; |
- Init(); |
-} |
- |
- |
-void Log::OpenFile(const char* name) { |
- ASSERT(!IsEnabled()); |
- output_handle_ = OS::FOpen(name, OS::LogFileOpenMode); |
- Write = WriteToFile; |
- Init(); |
-} |
- |
- |
-void Log::OpenMemoryBuffer() { |
- ASSERT(!IsEnabled()); |
- output_buffer_ = NewArray<char>(kOutputBufferSize); |
- output_buffer_write_pos_ = output_buffer_; |
- Write = WriteToMemory; |
- Init(); |
-} |
- |
- |
-void Log::Close() { |
- if (Write == WriteToFile) { |
- fclose(output_handle_); |
- output_handle_ = NULL; |
- } else if (Write == WriteToMemory) { |
- DeleteArray(output_buffer_); |
- output_buffer_ = NULL; |
- } else { |
- ASSERT(Write == NULL); |
- } |
- Write = NULL; |
- |
- delete mutex_; |
- mutex_ = NULL; |
- |
- DeleteArray(message_buffer_); |
- message_buffer_ = NULL; |
-} |
- |
- |
-int Log::GetLogLines(int from_pos, char* dest_buf, int max_size) { |
- if (Write != WriteToMemory) return 0; |
- ASSERT(output_buffer_ != NULL); |
- ASSERT(output_buffer_write_pos_ >= output_buffer_); |
- ASSERT(from_pos >= 0); |
- ASSERT(max_size >= 0); |
- int actual_size = max_size; |
- char* buffer_read_pos = output_buffer_ + from_pos; |
- ScopedLock sl(mutex_); |
- if (actual_size == 0 |
- || output_buffer_write_pos_ == output_buffer_ |
- || buffer_read_pos >= output_buffer_write_pos_) { |
- // No data requested or can be returned. |
- return 0; |
- } |
- if (buffer_read_pos + actual_size > output_buffer_write_pos_) { |
- // Requested size overlaps with current writing position and |
- // needs to be truncated. |
- actual_size = output_buffer_write_pos_ - buffer_read_pos; |
- ASSERT(actual_size == 0 || buffer_read_pos[actual_size - 1] == '\n'); |
- } else { |
- // Find previous log line boundary. |
- char* end_pos = buffer_read_pos + actual_size - 1; |
- while (end_pos >= buffer_read_pos && *end_pos != '\n') --end_pos; |
- actual_size = end_pos - buffer_read_pos + 1; |
- } |
- ASSERT(actual_size <= max_size); |
- if (actual_size > 0) { |
- memcpy(dest_buf, buffer_read_pos, actual_size); |
- } |
- return actual_size; |
-} |
- |
- |
-// Utility class for formatting log messages. It fills the message into the |
-// static buffer in Log. |
-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(); |
- void WriteCStringToLogFile(const char* str); |
- |
- 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(Log::mutex_), pos_(0) { |
- ASSERT(Log::message_buffer_ != NULL); |
-} |
- |
- |
-// Append string data to the log message. |
-void LogMessageBuilder::Append(const char* format, ...) { |
- Vector<char> buf(Log::message_buffer_ + pos_, |
- Log::kMessageBufferSize - pos_); |
- va_list args; |
- va_start(args, format); |
- Append(format, args); |
- va_end(args); |
- ASSERT(pos_ <= Log::kMessageBufferSize); |
-} |
- |
- |
-// Append string data to the log message. |
-void LogMessageBuilder::Append(const char* format, va_list args) { |
- Vector<char> buf(Log::message_buffer_ + pos_, |
- Log::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_ = Log::kMessageBufferSize; |
- } |
- ASSERT(pos_ <= Log::kMessageBufferSize); |
-} |
- |
- |
-// Append a character to the log message. |
-void LogMessageBuilder::Append(const char c) { |
- if (pos_ < Log::kMessageBufferSize) { |
- Log::message_buffer_[pos_++] = c; |
- } |
- ASSERT(pos_ <= Log::kMessageBufferSize); |
-} |
- |
- |
-// Append a heap string. |
-void LogMessageBuilder::Append(String* str) { |
- AssertNoAllocation no_heap_allocation; // Ensure string stay valid. |
- int length = str->length(); |
- for (int i = 0; i < length; i++) { |
- Append(static_cast<char>(str->Get(i))); |
- } |
-} |
- |
-void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) { |
- AssertNoAllocation no_heap_allocation; // Ensure string stay valid. |
- int len = str->length(); |
- if (len > 0x1000) |
- len = 0x1000; |
- if (show_impl_info) { |
- Append(str->IsAsciiRepresentation() ? 'a' : '2'); |
- if (StringShape(str).IsExternal()) |
- Append('e'); |
- if (StringShape(str).IsSymbol()) |
- Append('#'); |
- Append(":%i:", str->length()); |
- } |
- for (int i = 0; i < len; i++) { |
- uc32 c = str->Get(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_ <= Log::kMessageBufferSize); |
- Log::Write(Log::message_buffer_, pos_); |
-} |
- |
-// Write a null-terminated string to to the log file currently opened. |
-void LogMessageBuilder::WriteCStringToLogFile(const char* str) { |
- int len = strlen(str); |
- Log::Write(str, len); |
-} |
-#endif |
- |
- |
// |
// Logger class implementation. |
// |