1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_LOG_UTILS_H_ 6 #define V8_LOG_UTILS_H_ 7 8 #include <stdio.h> 9 10 #include <cstdarg> 11 12 #include "src/allocation.h" 13 #include "src/base/compiler-specific.h" 14 #include "src/base/optional.h" 15 #include "src/base/platform/mutex.h" 16 #include "src/flags.h" 17 #include "src/ostreams.h" 18 19 namespace v8 { 20 namespace internal { 21 22 class Logger; 23 template <typename T> 24 class Vector; 25 26 enum class LogSeparator { kSeparator }; 27 28 // Functions and data for performing output of log messages. 29 class Log { 30 public: 31 Log(Logger* log, const char* log_file_name); 32 // Disables logging, but preserves acquired resources. stop()33 void stop() { is_stopped_ = true; } 34 InitLogAtStart()35 static bool InitLogAtStart() { 36 return FLAG_log || FLAG_log_api || FLAG_log_code || FLAG_log_handles || 37 FLAG_log_suspect || FLAG_ll_prof || FLAG_perf_basic_prof || 38 FLAG_perf_prof || FLAG_log_source_code || FLAG_gdbjit || 39 FLAG_log_internal_timer_events || FLAG_prof_cpp || FLAG_trace_ic || 40 FLAG_log_function_events; 41 } 42 43 // Frees all resources acquired in Initialize and Open... functions. 44 // When a temporary file is used for the log, returns its stream descriptor, 45 // leaving the file open. 46 FILE* Close(); 47 48 // Returns whether logging is enabled. IsEnabled()49 bool IsEnabled() { return !is_stopped_ && output_handle_ != nullptr; } 50 51 // Size of buffer used for formatting log messages. 52 static const int kMessageBufferSize = 2048; 53 54 // This mode is only used in tests, as temporary files are automatically 55 // deleted on close and thus can't be accessed afterwards. 56 static const char* const kLogToTemporaryFile; 57 static const char* const kLogToConsole; 58 59 // Utility class for formatting log messages. It escapes the given messages 60 // and then appends them to the static buffer in Log. 61 class MessageBuilder BASE_EMBEDDED { 62 public: 63 // Create a message builder starting from position 0. 64 // This acquires the mutex in the log as well. 65 explicit MessageBuilder(Log* log); ~MessageBuilder()66 ~MessageBuilder() { } 67 68 void AppendString(String* str, 69 base::Optional<int> length_limit = base::nullopt); 70 void AppendString(Vector<const char> str); 71 void AppendString(const char* str); 72 void AppendString(const char* str, size_t length); 73 void PRINTF_FORMAT(2, 3) AppendFormatString(const char* format, ...); 74 void AppendCharacter(char c); 75 void AppendSymbolName(Symbol* symbol); 76 77 // Delegate insertion to the underlying {log_}. 78 // All appended strings are escaped to maintain one-line log entries. 79 template <typename T> 80 MessageBuilder& operator<<(T value) { 81 log_->os_ << value; 82 return *this; 83 } 84 85 // Finish the current log line an flush the it to the log file. 86 void WriteToLogFile(); 87 88 private: 89 // Prints the format string into |log_->format_buffer_|. Returns the length 90 // of the result, or kMessageBufferSize if it was truncated. 91 int PRINTF_FORMAT(2, 0) 92 FormatStringIntoBuffer(const char* format, va_list args); 93 94 void AppendSymbolNameDetails(String* str, bool show_impl_info); 95 96 void PRINTF_FORMAT(2, 3) AppendRawFormatString(const char* format, ...); 97 void AppendRawCharacter(const char character); 98 99 Log* log_; 100 base::LockGuard<base::Mutex> lock_guard_; 101 }; 102 103 private: 104 static FILE* CreateOutputHandle(const char* file_name); 105 106 // Implementation of writing to a log file. WriteToFile(const char * msg,int length)107 int WriteToFile(const char* msg, int length) { 108 DCHECK_NOT_NULL(output_handle_); 109 os_.write(msg, length); 110 DCHECK(!os_.bad()); 111 return length; 112 } 113 114 // Whether logging is stopped (e.g. due to insufficient resources). 115 bool is_stopped_; 116 117 // When logging is active output_handle_ is used to store a pointer to log 118 // destination. mutex_ should be acquired before using output_handle_. 119 FILE* output_handle_; 120 OFStream os_; 121 122 // mutex_ is a Mutex used for enforcing exclusive 123 // access to the formatting buffer and the log file or log memory buffer. 124 base::Mutex mutex_; 125 126 // Buffer used for formatting log messages. This is a singleton buffer and 127 // mutex_ should be acquired before using it. 128 char* format_buffer_; 129 130 Logger* logger_; 131 132 friend class Logger; 133 }; 134 135 template <> 136 Log::MessageBuilder& Log::MessageBuilder::operator<<<LogSeparator>( 137 LogSeparator separator); 138 template <> 139 Log::MessageBuilder& Log::MessageBuilder::operator<<<void*>(void* pointer); 140 template <> 141 Log::MessageBuilder& Log::MessageBuilder::operator<<<const char*>( 142 const char* string); 143 template <> 144 Log::MessageBuilder& Log::MessageBuilder::operator<<<char>(char c); 145 template <> 146 Log::MessageBuilder& Log::MessageBuilder::operator<<<String*>(String* string); 147 template <> 148 Log::MessageBuilder& Log::MessageBuilder::operator<<<Symbol*>(Symbol* symbol); 149 template <> 150 Log::MessageBuilder& Log::MessageBuilder::operator<<<Name*>(Name* name); 151 152 } // namespace internal 153 } // namespace v8 154 155 #endif // V8_LOG_UTILS_H_ 156