'flags.cc', 'frames.cc', 'func-name-inferrer.cc',
'global-handles.cc', 'handles.cc', 'hashmap.cc',
'heap.cc', 'ic.cc', 'interpreter-irregexp.cc', 'jsregexp.cc',
- 'jump-target.cc', 'log.cc', 'mark-compact.cc', 'messages.cc', 'objects.cc',
- 'oprofile-agent.cc', 'parser.cc', 'property.cc', 'regexp-macro-assembler.cc',
- 'regexp-macro-assembler-irregexp.cc', 'regexp-stack.cc',
- 'register-allocator.cc', 'rewriter.cc', 'runtime.cc', 'scanner.cc',
- 'scopeinfo.cc', 'scopes.cc', 'serialize.cc', 'snapshot-common.cc',
- 'spaces.cc', 'string-stream.cc', 'stub-cache.cc', 'token.cc', 'top.cc',
- 'unicode.cc', 'usage-analyzer.cc', 'utils.cc', 'v8-counters.cc',
- 'v8.cc', 'v8threads.cc', 'variables.cc', 'version.cc',
+ 'jump-target.cc', 'log.cc', 'log-utils.cc', 'mark-compact.cc', 'messages.cc',
+ 'objects.cc', 'oprofile-agent.cc', 'parser.cc', 'property.cc',
+ 'regexp-macro-assembler.cc', 'regexp-macro-assembler-irregexp.cc',
+ 'regexp-stack.cc', 'register-allocator.cc', 'rewriter.cc', 'runtime.cc',
+ 'scanner.cc', 'scopeinfo.cc', 'scopes.cc', 'serialize.cc',
+ 'snapshot-common.cc', 'spaces.cc', 'string-stream.cc', 'stub-cache.cc',
+ 'token.cc', 'top.cc', 'unicode.cc', 'usage-analyzer.cc', 'utils.cc',
+ 'v8-counters.cc', 'v8.cc', 'v8threads.cc', 'variables.cc', 'version.cc',
'virtual-frame.cc', 'zone.cc'
],
'arch:arm': [
--- /dev/null
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "log-utils.h"
+
+namespace v8 {
+namespace internal {
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+LogDynamicBuffer::LogDynamicBuffer(int block_size, int max_size)
+ : block_size_(block_size),
+ max_size_(max_size - (max_size % block_size_)),
+ blocks_(max_size_ / block_size_ + 1),
+ write_pos_(0), block_index_(0), block_write_pos_(0) {
+ ASSERT(BlocksCount() > 0);
+ AllocateBlock(0);
+ for (int i = 1; i < BlocksCount(); ++i) {
+ blocks_[i] = NULL;
+ }
+}
+
+
+LogDynamicBuffer::~LogDynamicBuffer() {
+ for (int i = 0; i < BlocksCount(); ++i) {
+ DeleteArray(blocks_[i]);
+ }
+}
+
+
+int LogDynamicBuffer::Read(int from_pos, char* dest_buf, int buf_size) {
+ if (buf_size == 0) return 0;
+ int read_pos = from_pos;
+ int block_read_index = BlockIndex(from_pos);
+ int block_read_pos = PosInBlock(from_pos);
+ int dest_buf_pos = 0;
+ // Read until dest_buf is filled, or write_pos_ encountered.
+ while (read_pos < write_pos_ && dest_buf_pos < buf_size) {
+ const int read_size = Min(write_pos_ - read_pos,
+ Min(buf_size - dest_buf_pos, block_size_ - block_read_pos));
+ memcpy(dest_buf + dest_buf_pos,
+ blocks_[block_read_index] + block_read_pos, read_size);
+ block_read_pos += read_size;
+ dest_buf_pos += read_size;
+ read_pos += read_size;
+ if (block_read_pos == block_size_) {
+ block_read_pos = 0;
+ ++block_read_index;
+ }
+ }
+ return dest_buf_pos;
+}
+
+
+int LogDynamicBuffer::Write(const char* data, int data_size) {
+ if ((write_pos_ + data_size) > max_size_) return 0;
+ int data_pos = 0;
+ while (data_pos < data_size) {
+ const int write_size =
+ Min(data_size - data_pos, block_size_ - block_write_pos_);
+ memcpy(blocks_[block_index_] + block_write_pos_, data + data_pos,
+ write_size);
+ block_write_pos_ += write_size;
+ data_pos += write_size;
+ if (block_write_pos_ == block_size_) {
+ block_write_pos_ = 0;
+ AllocateBlock(++block_index_);
+ }
+ }
+ write_pos_ += data_size;
+ return data_size;
+}
+
+
+Log::WritePtr Log::Write = NULL;
+FILE* Log::output_handle_ = NULL;
+LogDynamicBuffer* Log::output_buffer_ = NULL;
+Mutex* Log::mutex_ = 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_ = new LogDynamicBuffer(
+ kDynamicBufferBlockSize, kMaxDynamicBufferSize);
+ Write = WriteToMemory;
+ Init();
+}
+
+
+void Log::Close() {
+ if (Write == WriteToFile) {
+ fclose(output_handle_);
+ output_handle_ = NULL;
+ } else if (Write == WriteToMemory) {
+ delete output_buffer_;
+ output_buffer_ = NULL;
+ } else {
+ ASSERT(Write == NULL);
+ }
+ Write = NULL;
+
+ delete mutex_;
+ mutex_ = NULL;
+}
+
+
+int Log::GetLogLines(int from_pos, char* dest_buf, int max_size) {
+ if (Write != WriteToMemory) return 0;
+ ASSERT(output_buffer_ != NULL);
+ ASSERT(from_pos >= 0);
+ ASSERT(max_size >= 0);
+ int actual_size = output_buffer_->Read(from_pos, dest_buf, max_size);
+ ASSERT(actual_size <= max_size);
+ if (actual_size == 0) return 0;
+
+ // Find previous log line boundary.
+ char* end_pos = dest_buf + actual_size - 1;
+ while (end_pos >= dest_buf && *end_pos != '\n') --end_pos;
+ actual_size = end_pos - dest_buf + 1;
+ ASSERT(actual_size <= max_size);
+ return actual_size;
+}
+
+
+LogMessageBuilder::LogMessageBuilder(): sl(Log::mutex_), pos_(0) {
+ ASSERT(Log::message_buffer_ != NULL);
+}
+
+
+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);
+}
+
+
+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);
+}
+
+
+void LogMessageBuilder::Append(const char c) {
+ if (pos_ < Log::kMessageBufferSize) {
+ Log::message_buffer_[pos_++] = c;
+ }
+ ASSERT(pos_ <= Log::kMessageBufferSize);
+}
+
+
+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);
+ }
+ }
+}
+
+
+void LogMessageBuilder::WriteToLogFile() {
+ ASSERT(pos_ <= Log::kMessageBufferSize);
+ Log::Write(Log::message_buffer_, pos_);
+}
+
+
+void LogMessageBuilder::WriteCStringToLogFile(const char* str) {
+ int len = strlen(str);
+ Log::Write(str, len);
+}
+
+#endif // ENABLE_LOGGING_AND_PROFILING
+
+} } // namespace v8::internal
--- /dev/null
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_LOG_UTILS_H_
+#define V8_LOG_UTILS_H_
+
+namespace v8 {
+namespace internal {
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+// A memory buffer that increments its size as you write in it. Size
+// is incremented with 'block_size' steps, never exceeding 'max_size'.
+// During growth, memory contents are never copied.
+//
+// An instance of this class is created dynamically by Log.
+class LogDynamicBuffer {
+ public:
+ LogDynamicBuffer(int block_size, int max_size);
+
+ ~LogDynamicBuffer();
+
+ // Reads contents of the buffer starting from 'from_pos'. Upon
+ // return, 'dest_buf' is filled with the data. Actual amount of data
+ // filled is returned, it is <= 'buf_size'.
+ int Read(int from_pos, char* dest_buf, int buf_size);
+
+ // Writes 'data' to the buffer, making it larger if necessary. If
+ // data is too big to fit in the buffer, it doesn't get written at
+ // all. Returns amount of data written (it is either 'data_size', or
+ // 0, if 'data' is too big).
+ int Write(const char* data, int data_size);
+
+ private:
+ void AllocateBlock(int index) {
+ blocks_[index] = NewArray<char>(block_size_);
+ }
+
+ int BlockIndex(int pos) const { return pos / block_size_; }
+
+ int BlocksCount() const { return BlockIndex(max_size_) + 1; }
+
+ int PosInBlock(int pos) const { return pos % block_size_; }
+
+ const int block_size_;
+ const int max_size_;
+ ScopedVector<char*> blocks_;
+ int write_pos_;
+ int block_index_;
+ int block_write_pos_;
+};
+
+
+// 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);
+ return output_buffer_->Write(msg, length);
+ }
+
+ // 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 LogDynamicBuffer* output_buffer_;
+
+ // Size of dynamic buffer block (and dynamic buffer initial size).
+ static const int kDynamicBufferBlockSize = 65536;
+
+ // Maximum size of dynamic buffer.
+ static const int kMaxDynamicBufferSize = 50 * 1024 * 1024;
+
+ // 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 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;
+};
+
+
+// Utility class for formatting log messages. It fills the message into the
+// static buffer in Log.
+class LogMessageBuilder BASE_EMBEDDED {
+ public:
+ // Create a message builder starting from position 0. This acquires the mutex
+ // in the log as well.
+ explicit LogMessageBuilder();
+ ~LogMessageBuilder() { }
+
+ // Append string data to the log message.
+ void Append(const char* format, ...);
+
+ // Append string data to the log message.
+ void Append(const char* format, va_list args);
+
+ // Append a character to the log message.
+ void Append(const char c);
+
+ // Append a heap string.
+ void Append(String* str);
+
+ void AppendDetailed(String* str, bool show_impl_info);
+
+ // Write the log message to the log file currently opened.
+ void WriteToLogFile();
+
+ // Write a null-terminated string to to the log file currently opened.
+ void WriteCStringToLogFile(const char* str);
+
+ private:
+ ScopedLock sl;
+ int pos_;
+};
+
+#endif // ENABLE_LOGGING_AND_PROFILING
+
+} } // namespace v8::internal
+
+#endif // V8_LOG_UTILS_H_
#include "bootstrapper.h"
#include "log.h"
+#include "log-utils.h"
#include "macro-assembler.h"
#include "platform.h"
#include "serialize.h"
}
-#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.
//
'test-list.cc',
'test-lock.cc',
'test-log.cc',
+ 'test-log-utils.cc',
'test-mark-compact.cc',
'test-regexp.cc',
'test-serialize.cc',
--- /dev/null
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
+//
+// Tests of logging utilities from log-utils.h
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+#include "v8.h"
+
+#include "log-utils.h"
+#include "cctest.h"
+
+using v8::internal::EmbeddedVector;
+using v8::internal::LogDynamicBuffer;
+using v8::internal::Vector;
+
+// Fills 'ref_buffer' with test data: a sequence of two-digit
+// hex numbers: '0001020304...'. Then writes 'ref_buffer' contents to 'dynabuf'.
+static void WriteData(LogDynamicBuffer* dynabuf, Vector<char>* ref_buffer) {
+ static const char kHex[] = "0123456789ABCDEF";
+ CHECK_GT(ref_buffer->length(), 0);
+ CHECK_GT(513, ref_buffer->length());
+ for (int i = 0, half_len = ref_buffer->length() >> 1; i < half_len; ++i) {
+ (*ref_buffer)[i << 1] = kHex[i >> 4];
+ (*ref_buffer)[(i << 1) + 1] = kHex[i & 15];
+ }
+ if (ref_buffer->length() & 1) {
+ ref_buffer->last() = kHex[ref_buffer->length() >> 5];
+ }
+ CHECK_EQ(ref_buffer->length(),
+ dynabuf->Write(ref_buffer->start(), ref_buffer->length()));
+}
+
+
+static int ReadData(
+ LogDynamicBuffer* dynabuf, int start_pos, i::Vector<char>* buffer) {
+ return dynabuf->Read(start_pos, buffer->start(), buffer->length());
+}
+
+
+// Helper function used by CHECK_EQ to compare Vectors.
+static inline void CheckEqualsHelper(const char* file, int line,
+ const char* expected_source,
+ const Vector<char>& expected,
+ const char* value_source,
+ const Vector<char>& value) {
+ if (expected.length() != value.length()) {
+ V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n"
+ "# Vectors lengths differ: %d expected, %d found",
+ expected_source, value_source,
+ expected.length(), value.length());
+ }
+ if (strncmp(expected.start(), value.start(), expected.length()) != 0) {
+ V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n"
+ "# Vectors contents differ:\n"
+ "# Expected: %.*s\n"
+ "# Found: %.*s",
+ expected_source, value_source,
+ expected.length(), expected.start(),
+ value.length(), value.start());
+ }
+}
+
+
+TEST(DynaBufSingleBlock) {
+ LogDynamicBuffer dynabuf(32, 32);
+ EmbeddedVector<char, 32> ref_buf;
+ WriteData(&dynabuf, &ref_buf);
+ EmbeddedVector<char, 32> buf;
+ CHECK_EQ(32, dynabuf.Read(0, buf.start(), buf.length()));
+ CHECK_EQ(32, ReadData(&dynabuf, 0, &buf));
+ CHECK_EQ(ref_buf, buf);
+
+ // Verify that we can't read and write past the end.
+ CHECK_EQ(0, dynabuf.Read(32, buf.start(), buf.length()));
+ CHECK_EQ(0, dynabuf.Write(buf.start(), buf.length()));
+}
+
+
+TEST(DynaBufCrossBlocks) {
+ LogDynamicBuffer dynabuf(32, 128);
+ EmbeddedVector<char, 48> ref_buf;
+ WriteData(&dynabuf, &ref_buf);
+ CHECK_EQ(48, dynabuf.Write(ref_buf.start(), ref_buf.length()));
+ // Verify that we can't write data when remaining buffer space isn't enough.
+ CHECK_EQ(0, dynabuf.Write(ref_buf.start(), ref_buf.length()));
+ EmbeddedVector<char, 48> buf;
+ CHECK_EQ(48, ReadData(&dynabuf, 0, &buf));
+ CHECK_EQ(ref_buf, buf);
+ CHECK_EQ(48, ReadData(&dynabuf, 48, &buf));
+ CHECK_EQ(ref_buf, buf);
+ CHECK_EQ(0, ReadData(&dynabuf, 48 * 2, &buf));
+}
+
+
+TEST(DynaBufReadTruncation) {
+ LogDynamicBuffer dynabuf(32, 128);
+ EmbeddedVector<char, 128> ref_buf;
+ WriteData(&dynabuf, &ref_buf);
+ EmbeddedVector<char, 128> buf;
+ CHECK_EQ(128, ReadData(&dynabuf, 0, &buf));
+ CHECK_EQ(ref_buf, buf);
+ // Try to read near the end with a buffer larger than remaining data size.
+ EmbeddedVector<char, 48> tail_buf;
+ CHECK_EQ(32, ReadData(&dynabuf, 128 - 32, &tail_buf));
+ CHECK_EQ(ref_buf.SubVector(128 - 32, 128), tail_buf.SubVector(0, 32));
+}
+
+#endif // ENABLE_LOGGING_AND_PROFILING
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));
+ log_lines[line_1_len] = '\0';
CHECK_EQ(line_1, log_lines);
memset(log_lines, 0, sizeof(log_lines));
const char* line_2 = "cccc,\"dddd\"\n";
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
-#
+#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
-#
+#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
'../../src/list.h',
'../../src/log.cc',
'../../src/log.h',
+ '../../src/log-utils.cc',
+ '../../src/log-utils.h',
'../../src/macro-assembler.h',
'../../src/mark-compact.cc',
'../../src/mark-compact.h',
89F23C9F0E78D604006B2466 /* simulator-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF17D0E719B8F00D62E90 /* simulator-arm.cc */; };
89F23CA00E78D609006B2466 /* stub-cache-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF18A0E719B8F00D62E90 /* stub-cache-arm.cc */; };
89FB0E3A0F8E533F00B04B3C /* d8-posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89FB0E360F8E531900B04B3C /* d8-posix.cc */; };
+ 9F4B7B890FCC877A00DC4117 /* log-utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F4B7B870FCC877A00DC4117 /* log-utils.cc */; };
+ 9F4B7B8A0FCC877A00DC4117 /* log-utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F4B7B870FCC877A00DC4117 /* log-utils.cc */; };
9F92FAA90F8F28AD0089F02C /* func-name-inferrer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F92FAA70F8F28AD0089F02C /* func-name-inferrer.cc */; };
9F92FAAA0F8F28AD0089F02C /* func-name-inferrer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9F92FAA70F8F28AD0089F02C /* func-name-inferrer.cc */; };
9FC86ABD0F5FEDAC00F22668 /* oprofile-agent.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9FC86ABB0F5FEDAC00F22668 /* oprofile-agent.cc */; };
89F23C950E78D5B6006B2466 /* v8_shell-arm */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "v8_shell-arm"; sourceTree = BUILT_PRODUCTS_DIR; };
89FB0E360F8E531900B04B3C /* d8-posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "d8-posix.cc"; path = "../src/d8-posix.cc"; sourceTree = "<group>"; };
89FB0E370F8E531900B04B3C /* d8-windows.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "d8-windows.cc"; path = "../src/d8-windows.cc"; sourceTree = "<group>"; };
+ 9F4B7B870FCC877A00DC4117 /* log-utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "log-utils.cc"; sourceTree = "<group>"; };
+ 9F4B7B880FCC877A00DC4117 /* log-utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "log-utils.h"; sourceTree = "<group>"; };
9F92FAA70F8F28AD0089F02C /* func-name-inferrer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "func-name-inferrer.cc"; sourceTree = "<group>"; };
9F92FAA80F8F28AD0089F02C /* func-name-inferrer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "func-name-inferrer.h"; sourceTree = "<group>"; };
9FC86ABB0F5FEDAC00F22668 /* oprofile-agent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "oprofile-agent.cc"; sourceTree = "<group>"; };
897FF1510E719B8F00D62E90 /* list.h */,
897FF1520E719B8F00D62E90 /* log.cc */,
897FF1530E719B8F00D62E90 /* log.h */,
+ 9F4B7B870FCC877A00DC4117 /* log-utils.cc */,
+ 9F4B7B880FCC877A00DC4117 /* log-utils.h */,
897FF1540E719B8F00D62E90 /* macro-assembler-arm.cc */,
897FF1550E719B8F00D62E90 /* macro-assembler-arm.h */,
897FF1560E719B8F00D62E90 /* macro-assembler-ia32.cc */,
58950D660F5551C200F3E8BA /* virtual-frame.cc in Sources */,
58950D670F5551C400F3E8BA /* virtual-frame-ia32.cc in Sources */,
89A88E2E0E71A6D60043BA31 /* zone.cc in Sources */,
+ 9F4B7B890FCC877A00DC4117 /* log-utils.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
58950D680F5551CB00F3E8BA /* virtual-frame.cc in Sources */,
58950D690F5551CE00F3E8BA /* virtual-frame-arm.cc in Sources */,
89F23C820E78D5B2006B2466 /* zone.cc in Sources */,
+ 9F4B7B8A0FCC877A00DC4117 /* log-utils.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
RelativePath="..\..\src\log.h"
>
</File>
+ <File
+ RelativePath="..\..\src\log-utils.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\log-utils.h"
+ >
+ </File>
<File
RelativePath="..\..\src\ia32\macro-assembler-ia32.cc"
>
RelativePath="..\..\src\log.h"
>
</File>
+ <File
+ RelativePath="..\..\src\log-utils.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\log-utils.h"
+ >
+ </File>
<File
RelativePath="..\..\src\arm\macro-assembler-arm.cc"
>
RelativePath="..\..\test\cctest\test-log.cc"
>
</File>
+ <File
+ RelativePath="..\..\test\cctest\test-log-utils.cc"
+ >
+ </File>
<File
RelativePath="..\..\test\cctest\test-log-ia32.cc"
>
RelativePath="..\..\test\cctest\test-log.cc"
>
</File>
+ <File
+ RelativePath="..\..\test\cctest\test-log-utils.cc"
+ >
+ </File>
<File
RelativePath="..\..\test\cctest\test-mark-compact.cc"
>