blob: 719d37030e12d85ae521792f793973a2a489d45f [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2009 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_LOG_UTILS_H_
29#define V8_LOG_UTILS_H_
30
31namespace v8 {
32namespace internal {
33
34#ifdef ENABLE_LOGGING_AND_PROFILING
35
36// A memory buffer that increments its size as you write in it. Size
37// is incremented with 'block_size' steps, never exceeding 'max_size'.
38// During growth, memory contents are never copied. At the end of the
39// buffer an amount of memory specified in 'seal_size' is reserved.
40// When writing position reaches max_size - seal_size, buffer auto-seals
41// itself with 'seal' and allows no further writes. Data pointed by
42// 'seal' must be available during entire LogDynamicBuffer lifetime.
43//
44// An instance of this class is created dynamically by Log.
45class LogDynamicBuffer {
46 public:
47 LogDynamicBuffer(
48 int block_size, int max_size, const char* seal, int seal_size);
49
50 ~LogDynamicBuffer();
51
52 // Reads contents of the buffer starting from 'from_pos'. Upon
53 // return, 'dest_buf' is filled with the data. Actual amount of data
54 // filled is returned, it is <= 'buf_size'.
55 int Read(int from_pos, char* dest_buf, int buf_size);
56
57 // Writes 'data' to the buffer, making it larger if necessary. If
58 // data is too big to fit in the buffer, it doesn't get written at
59 // all. In that case, buffer auto-seals itself and stops to accept
60 // any incoming writes. Returns amount of data written (it is either
61 // 'data_size', or 0, if 'data' is too big).
62 int Write(const char* data, int data_size);
63
64 private:
65 void AllocateBlock(int index) {
66 blocks_[index] = NewArray<char>(block_size_);
67 }
68
69 int BlockIndex(int pos) const { return pos / block_size_; }
70
71 int BlocksCount() const { return BlockIndex(max_size_) + 1; }
72
73 int PosInBlock(int pos) const { return pos % block_size_; }
74
75 int Seal();
76
77 int WriteInternal(const char* data, int data_size);
78
79 const int block_size_;
80 const int max_size_;
81 const char* seal_;
82 const int seal_size_;
83 ScopedVector<char*> blocks_;
84 int write_pos_;
85 int block_index_;
86 int block_write_pos_;
87 bool is_sealed_;
88};
89
90
91// Functions and data for performing output of log messages.
92class Log : public AllStatic {
93 public:
94 // Opens stdout for logging.
95 static void OpenStdout();
96
97 // Opens file for logging.
98 static void OpenFile(const char* name);
99
100 // Opens memory buffer for logging.
101 static void OpenMemoryBuffer();
102
103 // Disables logging, but preserves acquired resources.
104 static void stop() { is_stopped_ = true; }
105
106 // Frees all resources acquired in Open... functions.
107 static void Close();
108
109 // See description in include/v8.h.
110 static int GetLogLines(int from_pos, char* dest_buf, int max_size);
111
112 // Returns whether logging is enabled.
113 static bool IsEnabled() {
114 return !is_stopped_ && (output_handle_ != NULL || output_buffer_ != NULL);
115 }
116
117 // Size of buffer used for formatting log messages.
Steve Block6ded16b2010-05-10 14:33:55 +0100118 static const int kMessageBufferSize = v8::V8::kMinimumSizeForLogLinesBuffer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000119
120 private:
121 typedef int (*WritePtr)(const char* msg, int length);
122
123 // Initialization function called from Open... functions.
124 static void Init();
125
126 // Write functions assume that mutex_ is acquired by the caller.
127 static WritePtr Write;
128
129 // Implementation of writing to a log file.
130 static int WriteToFile(const char* msg, int length) {
131 ASSERT(output_handle_ != NULL);
Steve Blockd0582a62009-12-15 09:54:21 +0000132 size_t rv = fwrite(msg, 1, length, output_handle_);
133 ASSERT(static_cast<size_t>(length) == rv);
134 USE(rv);
Ben Murdochf87a2032010-10-22 12:50:53 +0100135 fflush(output_handle_);
Steve Blockd0582a62009-12-15 09:54:21 +0000136 return length;
Steve Blocka7e24c12009-10-30 11:49:00 +0000137 }
138
139 // Implementation of writing to a memory buffer.
140 static int WriteToMemory(const char* msg, int length) {
141 ASSERT(output_buffer_ != NULL);
142 return output_buffer_->Write(msg, length);
143 }
144
145 // Whether logging is stopped (e.g. due to insufficient resources).
146 static bool is_stopped_;
147
148 // When logging is active, either output_handle_ or output_buffer_ is used
149 // to store a pointer to log destination. If logging was opened via OpenStdout
150 // or OpenFile, then output_handle_ is used. If logging was opened
151 // via OpenMemoryBuffer, then output_buffer_ is used.
152 // mutex_ should be acquired before using output_handle_ or output_buffer_.
153 static FILE* output_handle_;
154
Ben Murdochf87a2032010-10-22 12:50:53 +0100155 // Used when low-level profiling is active to save code object contents.
156 static FILE* output_code_handle_;
157
Steve Blocka7e24c12009-10-30 11:49:00 +0000158 static LogDynamicBuffer* output_buffer_;
159
160 // Size of dynamic buffer block (and dynamic buffer initial size).
161 static const int kDynamicBufferBlockSize = 65536;
162
163 // Maximum size of dynamic buffer.
164 static const int kMaxDynamicBufferSize = 50 * 1024 * 1024;
165
166 // Message to "seal" dynamic buffer with.
167 static const char* kDynamicBufferSeal;
168
169 // mutex_ is a Mutex used for enforcing exclusive
170 // access to the formatting buffer and the log file or log memory buffer.
171 static Mutex* mutex_;
172
173 // Buffer used for formatting log messages. This is a singleton buffer and
174 // mutex_ should be acquired before using it.
175 static char* message_buffer_;
176
Ben Murdochf87a2032010-10-22 12:50:53 +0100177 friend class Logger;
Steve Blocka7e24c12009-10-30 11:49:00 +0000178 friend class LogMessageBuilder;
Steve Blocka7e24c12009-10-30 11:49:00 +0000179};
180
181
182// Utility class for formatting log messages. It fills the message into the
183// static buffer in Log.
184class LogMessageBuilder BASE_EMBEDDED {
185 public:
186 // Create a message builder starting from position 0. This acquires the mutex
187 // in the log as well.
188 explicit LogMessageBuilder();
189 ~LogMessageBuilder() { }
190
191 // Append string data to the log message.
192 void Append(const char* format, ...);
193
194 // Append string data to the log message.
195 void AppendVA(const char* format, va_list args);
196
197 // Append a character to the log message.
198 void Append(const char c);
199
200 // Append a heap string.
201 void Append(String* str);
202
Ben Murdochb0fe1622011-05-05 13:52:32 +0100203 // Appends an address.
Steve Blocka7e24c12009-10-30 11:49:00 +0000204 void AppendAddress(Address addr);
205
Steve Blocka7e24c12009-10-30 11:49:00 +0000206 void AppendDetailed(String* str, bool show_impl_info);
207
208 // Append a portion of a string.
209 void AppendStringPart(const char* str, int len);
210
Steve Blocka7e24c12009-10-30 11:49:00 +0000211 // Write the log message to the log file currently opened.
212 void WriteToLogFile();
213
Steve Blocka7e24c12009-10-30 11:49:00 +0000214 // A handler that is called when Log::Write fails.
215 typedef void (*WriteFailureHandler)();
216
217 static void set_write_failure_handler(WriteFailureHandler handler) {
218 write_failure_handler = handler;
219 }
220
221 private:
222 static WriteFailureHandler write_failure_handler;
223
224 ScopedLock sl;
225 int pos_;
226};
227
228#endif // ENABLE_LOGGING_AND_PROFILING
229
230} } // namespace v8::internal
231
232#endif // V8_LOG_UTILS_H_