v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
log-file.cc
Go to the documentation of this file.
1// Copyright 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
6
7#include <atomic>
8#include <memory>
9#include <optional>
10
13#include "src/base/strings.h"
14#include "src/base/vector.h"
16#include "src/common/globals.h"
18#include "src/logging/log.h"
21#include "src/objects/tagged.h"
23#include "src/utils/version.h"
24
25namespace v8 {
26namespace internal {
27
28const char* const LogFile::kLogToTemporaryFile = "+";
29const char* const LogFile::kLogToConsole = "-";
30
31// static
32FILE* LogFile::CreateOutputHandle(std::string file_name) {
33 // If we're logging anything, we need to open the log file.
34 if (!v8_flags.log) {
35 return nullptr;
37 return stdout;
40 } else {
42 }
43}
44
45// static
46bool LogFile::IsLoggingToConsole(std::string file_name) {
47 return file_name.compare(LogFile::kLogToConsole) == 0;
48}
49
50// static
51bool LogFile::IsLoggingToTemporaryFile(std::string file_name) {
52 return file_name.compare(LogFile::kLogToTemporaryFile) == 0;
53}
54
55LogFile::LogFile(V8FileLogger* logger, std::string file_name)
56 : logger_(logger),
57 file_name_(file_name),
58 output_handle_(LogFile::CreateOutputHandle(file_name)),
59 os_(output_handle_ == nullptr ? stdout : output_handle_),
60 format_buffer_(NewArray<char>(kMessageBufferSize)) {
62}
63
67 msg << "v8-version" << kNext << Version::GetMajor() << kNext
68 << Version::GetMinor() << kNext << Version::GetBuild() << kNext
70 if (strlen(Version::GetEmbedder()) != 0) {
71 msg << kNext << Version::GetEmbedder();
72 }
73 msg << kNext << Version::IsCandidate();
74 msg.WriteToLogFile();
75 msg << "v8-platform" << kNext << V8_OS_STRING << kNext << V8_TARGET_OS_STRING;
76 msg.WriteToLogFile();
77}
78
79std::unique_ptr<LogFile::MessageBuilder> LogFile::NewMessageBuilder() {
80 // Fast check of is_logging() without taking the lock. Bail out immediately if
81 // logging isn't enabled.
82 if (!logger_->is_logging()) return {};
83
84 std::unique_ptr<LogFile::MessageBuilder> result(
85 new LogFile::MessageBuilder(this));
86
87 // The first invocation of is_logging() might still read an old value. It is
88 // fine if a background thread starts logging a bit later, but we want to
89 // avoid background threads continue logging after logging was already closed.
90 if (!logger_->is_logging()) return {};
92
93 return result;
94}
95
97 FILE* result = nullptr;
98 if (output_handle_ != nullptr) {
99 fflush(output_handle_);
101 }
102 output_handle_ = nullptr;
103 format_buffer_.reset();
104 return result;
105}
106
107std::string LogFile::file_name() const { return file_name_; }
108
110 : log_(log), lock_guard_(&log_->mutex_) {}
111
113 std::optional<int> length_limit) {
114 if (str.is_null()) return;
115
116 DisallowGarbageCollection no_gc; // Ensure string stays valid.
117 SharedStringAccessGuardIfNeeded access_guard(str);
118 int length = str->length();
119 if (length_limit) length = std::min(length, *length_limit);
120 for (int i = 0; i < length; i++) {
121 uint16_t c = str->Get(i, access_guard);
122 if (c <= 0xFF) {
123 AppendCharacter(static_cast<char>(c));
124 } else {
125 // Escape non-ascii characters.
126 AppendRawFormatString("\\u%04x", c & 0xFFFF);
127 }
128 }
129}
130
132 for (auto i = str.begin(); i < str.end(); i++) AppendCharacter(*i);
133}
134
136 if (str == nullptr) return;
137 AppendString(str, strlen(str));
138}
139
140void LogFile::MessageBuilder::AppendString(const char* str, size_t length,
141 bool is_one_byte) {
142 if (str == nullptr) return;
143 if (is_one_byte) {
144 for (size_t i = 0; i < length; i++) {
145 DCHECK_IMPLIES(is_one_byte, str[i] != '\0');
146 AppendCharacter(str[i]);
147 }
148 } else {
149 DCHECK_EQ(length % 2, 0);
150 for (size_t i = 0; i + 1 < length; i += 2) {
151 AppendTwoByteCharacter(str[i], str[i + 1]);
152 }
153 }
154}
155
156void LogFile::MessageBuilder::AppendFormatString(const char* format, ...) {
157 va_list args;
158 va_start(args, format);
159 const int length = FormatStringIntoBuffer(format, args);
160 va_end(args);
161 for (int i = 0; i < length; i++) {
162 DCHECK_NE(log_->format_buffer_[i], '\0');
163 AppendCharacter(log_->format_buffer_[i]);
164 }
165}
166
168 if (c2 == 0) {
169 AppendCharacter(c1);
170 } else {
171 // Escape non-printable characters.
172 AppendRawFormatString("\\u%02x%02x", c1 & 0xFF, c2 & 0xFF);
173 }
174}
176 if (std::isprint(c)) {
177 if (c == ',') {
178 // Escape commas to avoid adding column separators.
179 AppendRawString("\\x2C");
180 } else if (c == '\\') {
181 AppendRawString("\\\\");
182 } else {
183 // Safe, printable ascii character.
184 AppendRawCharacter(c);
185 }
186 } else if (c == '\n') {
187 // Escape newlines to avoid adding row separators.
188 AppendRawString("\\n");
189 } else {
190 // Escape non-printable characters.
191 AppendRawFormatString("\\x%02x", c & 0xFF);
192 }
193}
194
196 DCHECK(!symbol.is_null());
197 OFStream& os = log_->os_;
198 os << "symbol(";
199 if (!IsUndefined(symbol->description())) {
200 os << "\"";
201 AppendSymbolNameDetails(Cast<String>(symbol->description()), false);
202 os << "\" ";
203 }
204 os << "hash " << std::hex << symbol->hash() << std::dec << ")";
205}
206
208 bool show_impl_info) {
209 if (str.is_null()) return;
210
211 DisallowGarbageCollection no_gc; // Ensure string stays valid.
212 OFStream& os = log_->os_;
213 int limit = str->length();
214 if (limit > 0x1000) limit = 0x1000;
215 if (show_impl_info) {
216 os << (str->IsOneByteRepresentation() ? 'a' : '2');
217 if (StringShape(str).IsExternal()) os << 'e';
218 if (StringShape(str).IsInternalized()) os << '#';
219 os << ':' << str->length() << ':';
220 }
221 AppendString(str, limit);
222}
223
224int LogFile::MessageBuilder::FormatStringIntoBuffer(const char* format,
225 va_list args) {
226 base::Vector<char> buf(log_->format_buffer_.get(),
228 int length = base::VSNPrintF(buf, format, args);
229 // |length| is -1 if output was truncated.
230 if (length == -1) length = LogFile::kMessageBufferSize;
232 DCHECK_GE(length, 0);
233 return length;
234}
235
236void LogFile::MessageBuilder::AppendRawFormatString(const char* format, ...) {
237 va_list args;
238 va_start(args, format);
239 const int length = FormatStringIntoBuffer(format, args);
240 va_end(args);
241 for (int i = 0; i < length; i++) {
242 DCHECK_NE(log_->format_buffer_[i], '\0');
243 AppendRawCharacter(log_->format_buffer_[i]);
244 }
245}
246
248 log_->os_ << str;
249}
250
251void LogFile::MessageBuilder::AppendRawCharacter(char c) { log_->os_ << c; }
252
253void LogFile::MessageBuilder::WriteToLogFile() { log_->os_ << std::endl; }
254
255template <>
256LogFile::MessageBuilder& LogFile::MessageBuilder::operator<<<const char*>(
257 const char* string) {
258 this->AppendString(string);
259 return *this;
260}
261
262template <>
263LogFile::MessageBuilder& LogFile::MessageBuilder::operator<<<void*>(
264 void* pointer) {
265 OFStream& os = log_->os_;
266 // Manually format the pointer since on Windows we do not consistently
267 // get a "0x" prefix.
268 os << "0x" << std::hex << reinterpret_cast<intptr_t>(pointer) << std::dec;
269 return *this;
270}
271
272template <>
273LogFile::MessageBuilder& LogFile::MessageBuilder::operator<<<char>(char c) {
274 this->AppendCharacter(c);
275 return *this;
276}
277
278template <>
279LogFile::MessageBuilder& LogFile::MessageBuilder::operator<< <Tagged<String>>(
281 this->AppendString(string);
282 return *this;
283}
284
285template <>
286LogFile::MessageBuilder& LogFile::MessageBuilder::operator<< <Tagged<Symbol>>(
287 Tagged<Symbol> symbol) {
288 this->AppendSymbolName(symbol);
289 return *this;
290}
291
292template <>
293LogFile::MessageBuilder& LogFile::MessageBuilder::operator<< <Tagged<Name>>(
295 if (IsString(name)) {
296 this->AppendString(Cast<String>(name));
297 } else {
298 this->AppendSymbolName(Cast<Symbol>(name));
299 }
300 return *this;
301}
302
303template <>
304LogFile::MessageBuilder& LogFile::MessageBuilder::operator<<<LogSeparator>(
306 // Skip escaping to create a new column.
307 this->AppendRawCharacter(',');
308 return *this;
309}
310
311} // namespace internal
312} // namespace v8
static const char *const LogFileOpenMode
Definition platform.h:194
static FILE * OpenTemporaryFile()
static FILE * FOpen(const char *path, const char *mode)
constexpr T * begin() const
Definition vector.h:96
constexpr T * end() const
Definition vector.h:103
void void AppendRawString(const char *format)
Definition log-file.cc:247
void AppendSymbolName(Tagged< Symbol > symbol)
Definition log-file.cc:195
void AppendSymbolNameDetails(Tagged< String > str, bool show_impl_info)
Definition log-file.cc:207
void AppendString(Tagged< String > str, std::optional< int > length_limit=std::nullopt)
Definition log-file.cc:112
void AppendRawCharacter(const char character)
Definition log-file.cc:251
void AppendTwoByteCharacter(char c1, char c2)
Definition log-file.cc:167
LogFile(V8FileLogger *logger, std::string log_file_name)
Definition log-file.cc:55
static FILE * CreateOutputHandle(std::string file_name)
Definition log-file.cc:32
static V8_EXPORT_PRIVATE bool IsLoggingToTemporaryFile(std::string file_name)
Definition log-file.cc:51
std::unique_ptr< LogFile::MessageBuilder > NewMessageBuilder()
Definition log-file.cc:79
V8FileLogger * logger_
Definition log-file.h:117
std::unique_ptr< char[]> format_buffer_
Definition log-file.h:133
std::string file_name() const
Definition log-file.cc:107
static V8_EXPORT_PRIVATE bool IsLoggingToConsole(std::string file_name)
Definition log-file.cc:46
std::string file_name_
Definition log-file.h:119
static const char *const kLogToConsole
Definition log-file.h:56
static const int kMessageBufferSize
Definition log-file.h:51
static V8_EXPORT_PRIVATE const char *const kLogToTemporaryFile
Definition log-file.h:55
V8_INLINE constexpr bool is_null() const
Definition tagged.h:502
V8_EXPORT_PRIVATE bool is_logging()
Definition log.cc:1336
static const char * GetEmbedder()
Definition version.h:28
static int GetMajor()
Definition version.h:24
static int GetBuild()
Definition version.h:26
static int GetPatch()
Definition version.h:27
static int GetMinor()
Definition version.h:25
static bool IsCandidate()
Definition version.h:29
base::Mutex & mutex_
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
ZoneVector< RpoNumber > & result
int VSNPrintF(Vector< char > str, const char *format, va_list args)
Definition strings.cc:16
Tagged(T object) -> Tagged< T >
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
V8_EXPORT_PRIVATE FlagValues v8_flags
T * NewArray(size_t size)
Definition allocation.h:43
template const char * string
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
std::ostream * os_
#define V8_TARGET_OS_STRING
Definition v8config.h:262