5 #include "src/log-utils.h" 7 #include "src/assert-scope.h" 8 #include "src/base/platform/platform.h" 9 #include "src/objects-inl.h" 10 #include "src/string-stream.h" 11 #include "src/utils.h" 12 #include "src/vector.h" 13 #include "src/version.h" 19 const char*
const Log::kLogToTemporaryFile =
"&";
20 const char*
const Log::kLogToConsole =
"-";
23 FILE* Log::CreateOutputHandle(
const char* file_name) {
25 if (!Log::InitLogAtStart()) {
27 }
else if (strcmp(file_name, kLogToConsole) == 0) {
29 }
else if (strcmp(file_name, kLogToTemporaryFile) == 0) {
30 return base::OS::OpenTemporaryFile();
32 return base::OS::FOpen(file_name, base::OS::LogFileOpenMode);
36 Log::Log(Logger* logger,
const char* file_name)
38 output_handle_(Log::CreateOutputHandle(file_name)),
39 os_(output_handle_ == nullptr ? stdout : output_handle_),
40 format_buffer_(NewArray<
char>(kMessageBufferSize)),
46 FLAG_log_suspect =
true;
47 FLAG_log_handles =
true;
48 FLAG_log_internal_timer_events =
true;
49 FLAG_log_function_events =
true;
53 if (FLAG_prof) FLAG_log_code =
true;
55 if (output_handle_ ==
nullptr)
return;
56 Log::MessageBuilder msg(
this);
57 LogSeparator kNext = LogSeparator::kSeparator;
58 msg <<
"v8-version" << kNext << Version::GetMajor() << kNext
59 << Version::GetMinor() << kNext << Version::GetBuild() << kNext
60 << Version::GetPatch();
61 if (strlen(Version::GetEmbedder()) != 0) {
62 msg << kNext << Version::GetEmbedder();
64 msg << kNext << Version::IsCandidate();
69 FILE* result =
nullptr;
70 if (output_handle_ !=
nullptr) {
71 if (strcmp(FLAG_logfile, kLogToTemporaryFile) != 0) {
72 fclose(output_handle_);
74 result = output_handle_;
77 output_handle_ =
nullptr;
79 DeleteArray(format_buffer_);
80 format_buffer_ =
nullptr;
86 Log::MessageBuilder::MessageBuilder(Log* log)
87 : log_(log), lock_guard_(&log_->mutex_) {
88 DCHECK_NOT_NULL(log_->format_buffer_);
91 void Log::MessageBuilder::AppendString(String str,
92 base::Optional<int> length_limit) {
93 if (str.is_null())
return;
95 DisallowHeapAllocation no_gc;
96 int length = str->length();
97 if (length_limit) length = std::min(length, *length_limit);
98 for (
int i = 0;
i < length;
i++) {
99 uint16_t c = str->Get(
i);
101 AppendCharacter(static_cast<char>(c));
104 AppendRawFormatString(
"\\u%04x", c & 0xFFFF);
109 void Log::MessageBuilder::AppendString(Vector<const char> str) {
110 for (
auto i = str.begin();
i < str.end();
i++) AppendCharacter(*
i);
113 void Log::MessageBuilder::AppendString(
const char* str) {
114 if (str ==
nullptr)
return;
115 AppendString(str, strlen(str));
118 void Log::MessageBuilder::AppendString(
const char* str,
size_t length) {
119 if (str ==
nullptr)
return;
121 for (
size_t i = 0;
i < length;
i++) {
122 DCHECK_NE(str[
i],
'\0');
123 AppendCharacter(str[
i]);
127 void Log::MessageBuilder::AppendFormatString(
const char* format, ...) {
129 va_start(args, format);
130 const int length = FormatStringIntoBuffer(format, args);
132 for (
int i = 0;
i < length;
i++) {
133 DCHECK_NE(log_->format_buffer_[
i],
'\0');
134 AppendCharacter(log_->format_buffer_[
i]);
138 void Log::MessageBuilder::AppendCharacter(
char c) {
139 if (c >= 32 && c <= 126) {
142 AppendRawFormatString(
"\\x2C");
143 }
else if (c ==
'\\') {
144 AppendRawFormatString(
"\\\\");
147 AppendRawCharacter(c);
149 }
else if (c ==
'\n') {
151 AppendRawFormatString(
"\\n");
154 AppendRawFormatString(
"\\x%02x", c & 0xFF);
158 void Log::MessageBuilder::AppendSymbolName(Symbol symbol) {
159 DCHECK(!symbol.is_null());
160 OFStream& os = log_->os_;
162 if (!symbol->name()->IsUndefined()) {
164 AppendSymbolNameDetails(String::cast(symbol->name()),
false);
167 os <<
"hash " << std::hex << symbol->Hash() << std::dec <<
")";
170 void Log::MessageBuilder::AppendSymbolNameDetails(String str,
171 bool show_impl_info) {
172 if (str.is_null())
return;
174 DisallowHeapAllocation no_gc;
175 OFStream& os = log_->os_;
176 int limit = str->length();
177 if (limit > 0x1000) limit = 0x1000;
178 if (show_impl_info) {
179 os << (str->IsOneByteRepresentation() ?
'a' :
'2');
180 if (StringShape(str).IsExternal()) os <<
'e';
181 if (StringShape(str).IsInternalized()) os <<
'#';
182 os <<
':' << str->length() <<
':';
184 AppendString(str, limit);
187 int Log::MessageBuilder::FormatStringIntoBuffer(
const char* format,
189 Vector<char> buf(log_->format_buffer_, Log::kMessageBufferSize);
190 int length = v8::internal::VSNPrintF(buf, format, args);
192 if (length == -1) length = Log::kMessageBufferSize;
193 DCHECK_LE(length, Log::kMessageBufferSize);
194 DCHECK_GE(length, 0);
198 void Log::MessageBuilder::AppendRawFormatString(
const char* format, ...) {
200 va_start(args, format);
201 const int length = FormatStringIntoBuffer(format, args);
203 for (
int i = 0;
i < length;
i++) {
204 DCHECK_NE(log_->format_buffer_[
i],
'\0');
205 AppendRawCharacter(log_->format_buffer_[
i]);
209 void Log::MessageBuilder::AppendRawCharacter(
char c) { log_->os_ << c; }
211 void Log::MessageBuilder::WriteToLogFile() { log_->os_ << std::endl; }
214 Log::MessageBuilder& Log::MessageBuilder::operator<<<const char*>(
215 const char* string) {
216 this->AppendString(
string);
221 Log::MessageBuilder& Log::MessageBuilder::operator<<<void*>(
void* pointer) {
222 OFStream& os = log_->os_;
225 os <<
"0x" << std::hex << reinterpret_cast<intptr_t>(pointer) << std::dec;
230 Log::MessageBuilder& Log::MessageBuilder::operator<<<char>(
char c) {
231 this->AppendCharacter(c);
236 Log::MessageBuilder& Log::MessageBuilder::operator<<<String>(String string) {
237 this->AppendString(
string);
242 Log::MessageBuilder& Log::MessageBuilder::operator<<<Symbol>(Symbol symbol) {
243 this->AppendSymbolName(symbol);
248 Log::MessageBuilder& Log::MessageBuilder::operator<<<Name>(Name name) {
249 if (name->IsString()) {
250 this->AppendString(String::cast(name));
252 this->AppendSymbolName(Symbol::cast(name));
258 Log::MessageBuilder& Log::MessageBuilder::operator<<<LogSeparator>(
259 LogSeparator separator) {
261 this->AppendRawCharacter(
',');