Home | History | Annotate | Download | only in src
      1 // 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 
     31 namespace v8 {
     32 namespace internal {
     33 
     34 #ifdef ENABLE_LOGGING_AND_PROFILING
     35 
     36 class Logger;
     37 
     38 // A memory buffer that increments its size as you write in it.  Size
     39 // is incremented with 'block_size' steps, never exceeding 'max_size'.
     40 // During growth, memory contents are never copied.  At the end of the
     41 // buffer an amount of memory specified in 'seal_size' is reserved.
     42 // When writing position reaches max_size - seal_size, buffer auto-seals
     43 // itself with 'seal' and allows no further writes. Data pointed by
     44 // 'seal' must be available during entire LogDynamicBuffer lifetime.
     45 //
     46 // An instance of this class is created dynamically by Log.
     47 class LogDynamicBuffer {
     48  public:
     49   LogDynamicBuffer(
     50       int block_size, int max_size, const char* seal, int seal_size);
     51 
     52   ~LogDynamicBuffer();
     53 
     54   // Reads contents of the buffer starting from 'from_pos'.  Upon
     55   // return, 'dest_buf' is filled with the data. Actual amount of data
     56   // filled is returned, it is <= 'buf_size'.
     57   int Read(int from_pos, char* dest_buf, int buf_size);
     58 
     59   // Writes 'data' to the buffer, making it larger if necessary.  If
     60   // data is too big to fit in the buffer, it doesn't get written at
     61   // all. In that case, buffer auto-seals itself and stops to accept
     62   // any incoming writes. Returns amount of data written (it is either
     63   // 'data_size', or 0, if 'data' is too big).
     64   int Write(const char* data, int data_size);
     65 
     66  private:
     67   void AllocateBlock(int index) {
     68     blocks_[index] = NewArray<char>(block_size_);
     69   }
     70 
     71   int BlockIndex(int pos) const { return pos / block_size_; }
     72 
     73   int BlocksCount() const { return BlockIndex(max_size_) + 1; }
     74 
     75   int PosInBlock(int pos) const { return pos % block_size_; }
     76 
     77   int Seal();
     78 
     79   int WriteInternal(const char* data, int data_size);
     80 
     81   const int block_size_;
     82   const int max_size_;
     83   const char* seal_;
     84   const int seal_size_;
     85   ScopedVector<char*> blocks_;
     86   int write_pos_;
     87   int block_index_;
     88   int block_write_pos_;
     89   bool is_sealed_;
     90 };
     91 
     92 
     93 // Functions and data for performing output of log messages.
     94 class Log {
     95  public:
     96 
     97   // Performs process-wide initialization.
     98   void Initialize();
     99 
    100   // Disables logging, but preserves acquired resources.
    101   void stop() { is_stopped_ = true; }
    102 
    103   // Frees all resources acquired in Initialize and Open... functions.
    104   void Close();
    105 
    106   // See description in include/v8.h.
    107   int GetLogLines(int from_pos, char* dest_buf, int max_size);
    108 
    109   // Returns whether logging is enabled.
    110   bool IsEnabled() {
    111     return !is_stopped_ && (output_handle_ != NULL || output_buffer_ != NULL);
    112   }
    113 
    114   // Size of buffer used for formatting log messages.
    115   static const int kMessageBufferSize = v8::V8::kMinimumSizeForLogLinesBuffer;
    116 
    117  private:
    118   explicit Log(Logger* logger);
    119 
    120   // Opens stdout for logging.
    121   void OpenStdout();
    122 
    123   // Opens file for logging.
    124   void OpenFile(const char* name);
    125 
    126   // Opens memory buffer for logging.
    127   void OpenMemoryBuffer();
    128 
    129   // Implementation of writing to a log file.
    130   int WriteToFile(const char* msg, int length) {
    131     ASSERT(output_handle_ != NULL);
    132     size_t rv = fwrite(msg, 1, length, output_handle_);
    133     ASSERT(static_cast<size_t>(length) == rv);
    134     USE(rv);
    135     fflush(output_handle_);
    136     return length;
    137   }
    138 
    139   // Implementation of writing to a memory buffer.
    140   int WriteToMemory(const char* msg, int length) {
    141     ASSERT(output_buffer_ != NULL);
    142     return output_buffer_->Write(msg, length);
    143   }
    144 
    145   bool write_to_file_;
    146 
    147   // Whether logging is stopped (e.g. due to insufficient resources).
    148   bool is_stopped_;
    149 
    150   // When logging is active, either output_handle_ or output_buffer_ is used
    151   // to store a pointer to log destination. If logging was opened via OpenStdout
    152   // or OpenFile, then output_handle_ is used. If logging was opened
    153   // via OpenMemoryBuffer, then output_buffer_ is used.
    154   // mutex_ should be acquired before using output_handle_ or output_buffer_.
    155   FILE* output_handle_;
    156 
    157   // Used when low-level profiling is active to save code object contents.
    158   FILE* output_code_handle_;
    159 
    160   LogDynamicBuffer* output_buffer_;
    161 
    162   // Size of dynamic buffer block (and dynamic buffer initial size).
    163   static const int kDynamicBufferBlockSize = 65536;
    164 
    165   // Maximum size of dynamic buffer.
    166   static const int kMaxDynamicBufferSize = 50 * 1024 * 1024;
    167 
    168   // Message to "seal" dynamic buffer with.
    169   static const char* const kDynamicBufferSeal;
    170 
    171   // mutex_ is a Mutex used for enforcing exclusive
    172   // access to the formatting buffer and the log file or log memory buffer.
    173   Mutex* mutex_;
    174 
    175   // Buffer used for formatting log messages. This is a singleton buffer and
    176   // mutex_ should be acquired before using it.
    177   char* message_buffer_;
    178 
    179   Logger* logger_;
    180 
    181   friend class Logger;
    182   friend class LogMessageBuilder;
    183 };
    184 
    185 
    186 // Utility class for formatting log messages. It fills the message into the
    187 // static buffer in Log.
    188 class LogMessageBuilder BASE_EMBEDDED {
    189  public:
    190   // Create a message builder starting from position 0. This acquires the mutex
    191   // in the log as well.
    192   explicit LogMessageBuilder(Logger* logger);
    193   ~LogMessageBuilder() { }
    194 
    195   // Append string data to the log message.
    196   void Append(const char* format, ...);
    197 
    198   // Append string data to the log message.
    199   void AppendVA(const char* format, va_list args);
    200 
    201   // Append a character to the log message.
    202   void Append(const char c);
    203 
    204   // Append a heap string.
    205   void Append(String* str);
    206 
    207   // Appends an address.
    208   void AppendAddress(Address addr);
    209 
    210   void AppendDetailed(String* str, bool show_impl_info);
    211 
    212   // Append a portion of a string.
    213   void AppendStringPart(const char* str, int len);
    214 
    215   // Write the log message to the log file currently opened.
    216   void WriteToLogFile();
    217 
    218  private:
    219 
    220   Log* log_;
    221   ScopedLock sl;
    222   int pos_;
    223 };
    224 
    225 #endif  // ENABLE_LOGGING_AND_PROFILING
    226 
    227 } }  // namespace v8::internal
    228 
    229 #endif  // V8_LOG_UTILS_H_
    230