diff options
Diffstat (limited to 'deps/v8/src/log-utils.cc')
-rw-r--r-- | deps/v8/src/log-utils.cc | 322 |
1 files changed, 143 insertions, 179 deletions
diff --git a/deps/v8/src/log-utils.cc b/deps/v8/src/log-utils.cc index 82d24a111e..b2eb44796d 100644 --- a/deps/v8/src/log-utils.cc +++ b/deps/v8/src/log-utils.cc @@ -18,15 +18,26 @@ namespace internal { const char* const Log::kLogToTemporaryFile = "&"; const char* const Log::kLogToConsole = "-"; -Log::Log(Logger* logger) - : is_stopped_(false), - output_handle_(NULL), - message_buffer_(NULL), - logger_(logger) {} - -void Log::Initialize(const char* log_file_name) { - message_buffer_ = NewArray<char>(kMessageBufferSize); +// static +FILE* Log::CreateOutputHandle(const char* file_name) { + // If we're logging anything, we need to open the log file. + if (!Log::InitLogAtStart()) { + return nullptr; + } else if (strcmp(file_name, kLogToConsole) == 0) { + return stdout; + } else if (strcmp(file_name, kLogToTemporaryFile) == 0) { + return base::OS::OpenTemporaryFile(); + } else { + return base::OS::FOpen(file_name, base::OS::LogFileOpenMode); + } +} +Log::Log(Logger* logger, const char* file_name) + : is_stopped_(false), + output_handle_(Log::CreateOutputHandle(file_name)), + os_(output_handle_ == nullptr ? stdout : output_handle_), + format_buffer_(NewArray<char>(kMessageBufferSize)), + logger_(logger) { // --log-all enables all the log flags. if (FLAG_log_all) { FLAG_log_api = true; @@ -35,245 +46,198 @@ void Log::Initialize(const char* log_file_name) { FLAG_log_suspect = true; FLAG_log_handles = true; FLAG_log_internal_timer_events = true; + FLAG_log_function_events = true; } // --prof implies --log-code. if (FLAG_prof) FLAG_log_code = true; - // If we're logging anything, we need to open the log file. - if (Log::InitLogAtStart()) { - if (strcmp(log_file_name, kLogToConsole) == 0) { - OpenStdout(); - } else if (strcmp(log_file_name, kLogToTemporaryFile) == 0) { - OpenTemporaryFile(); - } else { - OpenFile(log_file_name); - } - - if (output_handle_ != nullptr) { - Log::MessageBuilder msg(this); - if (strlen(Version::GetEmbedder()) == 0) { - msg.Append("v8-version,%d,%d,%d,%d,%d", Version::GetMajor(), - Version::GetMinor(), Version::GetBuild(), - Version::GetPatch(), Version::IsCandidate()); - } else { - msg.Append("v8-version,%d,%d,%d,%d,%s,%d", Version::GetMajor(), - Version::GetMinor(), Version::GetBuild(), - Version::GetPatch(), Version::GetEmbedder(), - Version::IsCandidate()); - } - msg.WriteToLogFile(); - } + if (output_handle_ == nullptr) return; + Log::MessageBuilder msg(this); + LogSeparator kNext = LogSeparator::kSeparator; + msg << "v8-version" << kNext << Version::GetMajor() << kNext + << Version::GetMinor() << kNext << Version::GetBuild() << kNext + << Version::GetPatch(); + if (strlen(Version::GetEmbedder()) != 0) { + msg << kNext << Version::GetEmbedder(); } -} - - -void Log::OpenStdout() { - DCHECK(!IsEnabled()); - output_handle_ = stdout; -} - - -void Log::OpenTemporaryFile() { - DCHECK(!IsEnabled()); - output_handle_ = base::OS::OpenTemporaryFile(); -} - - -void Log::OpenFile(const char* name) { - DCHECK(!IsEnabled()); - output_handle_ = base::OS::FOpen(name, base::OS::LogFileOpenMode); + msg << kNext << Version::IsCandidate(); + msg.WriteToLogFile(); } FILE* Log::Close() { - FILE* result = NULL; - if (output_handle_ != NULL) { + FILE* result = nullptr; + if (output_handle_ != nullptr) { if (strcmp(FLAG_logfile, kLogToTemporaryFile) != 0) { fclose(output_handle_); } else { result = output_handle_; } } - output_handle_ = NULL; + output_handle_ = nullptr; - DeleteArray(message_buffer_); - message_buffer_ = NULL; + DeleteArray(format_buffer_); + format_buffer_ = nullptr; is_stopped_ = false; return result; } - Log::MessageBuilder::MessageBuilder(Log* log) - : log_(log), - lock_guard_(&log_->mutex_), - pos_(0) { - DCHECK(log_->message_buffer_ != NULL); + : log_(log), lock_guard_(&log_->mutex_) { + DCHECK_NOT_NULL(log_->format_buffer_); } void Log::MessageBuilder::Append(const char* format, ...) { - Vector<char> buf(log_->message_buffer_ + pos_, - Log::kMessageBufferSize - pos_); va_list args; va_start(args, format); AppendVA(format, args); va_end(args); - DCHECK(pos_ <= Log::kMessageBufferSize); } void Log::MessageBuilder::AppendVA(const char* format, va_list args) { - Vector<char> buf(log_->message_buffer_ + pos_, - Log::kMessageBufferSize - pos_); - int result = v8::internal::VSNPrintF(buf, format, args); - - // Result is -1 if output was truncated. - if (result >= 0) { - pos_ += result; - } else { - pos_ = Log::kMessageBufferSize; - } - DCHECK(pos_ <= Log::kMessageBufferSize); + Vector<char> buf(log_->format_buffer_, Log::kMessageBufferSize); + int length = v8::internal::VSNPrintF(buf, format, args); + // {length} is -1 if output was truncated. + if (length == -1) length = Log::kMessageBufferSize; + DCHECK_LE(length, Log::kMessageBufferSize); + AppendStringPart(log_->format_buffer_, length); } - -void Log::MessageBuilder::Append(const char c) { - if (pos_ < Log::kMessageBufferSize) { - log_->message_buffer_[pos_++] = c; - } - DCHECK(pos_ <= Log::kMessageBufferSize); -} - - -void Log::MessageBuilder::AppendDoubleQuotedString(const char* string) { - Append('"'); - for (const char* p = string; *p != '\0'; p++) { - if (*p == '"') { - Append('\\'); - } - Append(*p); +void Log::MessageBuilder::AppendSymbolName(Symbol* symbol) { + DCHECK(symbol); + OFStream& os = log_->os_; + os << "symbol("; + if (!symbol->name()->IsUndefined(symbol->GetIsolate())) { + os << "\""; + AppendDetailed(String::cast(symbol->name()), false); + os << "\" "; } - Append('"'); + os << "hash " << std::hex << symbol->Hash() << std::dec << ")"; } - -void Log::MessageBuilder::Append(String* str) { +void Log::MessageBuilder::AppendDetailed(String* str, bool show_impl_info) { + if (str == nullptr) return; DisallowHeapAllocation no_gc; // Ensure string stay valid. - int length = str->length(); - for (int i = 0; i < length; i++) { - Append(static_cast<char>(str->Get(i))); + OFStream& os = log_->os_; + int limit = str->length(); + if (limit > 0x1000) limit = 0x1000; + if (show_impl_info) { + os << (str->IsOneByteRepresentation() ? 'a' : '2'); + if (StringShape(str).IsExternal()) os << 'e'; + if (StringShape(str).IsInternalized()) os << '#'; + os << ':' << str->length() << ':'; } + AppendStringPart(str, limit); } -void Log::MessageBuilder::AppendAddress(Address addr) { - Append("0x%" V8PRIxPTR, reinterpret_cast<intptr_t>(addr)); +void Log::MessageBuilder::AppendString(String* str) { + if (str == nullptr) return; + int len = str->length(); + AppendStringPart(str, len); } -void Log::MessageBuilder::AppendSymbolName(Symbol* symbol) { - DCHECK(symbol); - Append("symbol("); - if (!symbol->name()->IsUndefined(symbol->GetIsolate())) { - Append("\""); - AppendDetailed(String::cast(symbol->name()), false); - Append("\" "); +void Log::MessageBuilder::AppendString(const char* string) { + if (string == nullptr) return; + for (const char* p = string; *p != '\0'; p++) { + this->AppendCharacter(*p); } - Append("hash %x)", symbol->Hash()); } - -void Log::MessageBuilder::AppendDetailed(String* str, bool show_impl_info) { - if (str == NULL) return; +void Log::MessageBuilder::AppendStringPart(String* str, int len) { + DCHECK_LE(len, str->length()); DisallowHeapAllocation no_gc; // Ensure string stay valid. - int len = str->length(); - if (len > 0x1000) - len = 0x1000; - if (show_impl_info) { - Append(str->IsOneByteRepresentation() ? 'a' : '2'); - if (StringShape(str).IsExternal()) - Append('e'); - if (StringShape(str).IsInternalized()) - Append('#'); - Append(":%i:", str->length()); - } + // TODO(cbruni): unify escaping. for (int i = 0; i < len; i++) { uc32 c = str->Get(i); - if (c > 0xff) { - Append("\\u%04x", c); - } else if (c < 32 || c > 126) { - Append("\\x%02x", c); - } else if (c == ',') { - Append("\\,"); - } else if (c == '\\') { - Append("\\\\"); - } else if (c == '\"') { - Append("\"\""); + if (c <= 0xff) { + AppendCharacter(static_cast<char>(c)); } else { - Append("%lc", c); + // Escape any non-ascii range characters. + Append("\\u%04x", c); } } } -void Log::MessageBuilder::AppendUnbufferedHeapString(String* str) { - if (str == NULL) return; - DisallowHeapAllocation no_gc; // Ensure string stay valid. - ScopedVector<char> buffer(16); - int len = str->length(); - for (int i = 0; i < len; i++) { - uc32 c = str->Get(i); - if (c >= 32 && c <= 126) { - if (c == '\"') { - AppendUnbufferedCString("\"\""); - } else if (c == '\\') { - AppendUnbufferedCString("\\\\"); - } else { - AppendUnbufferedChar(c); - } - } else if (c > 0xff) { - int length = v8::internal::SNPrintF(buffer, "\\u%04x", c); - DCHECK_EQ(6, length); - log_->WriteToFile(buffer.start(), length); +void Log::MessageBuilder::AppendStringPart(const char* str, size_t len) { + for (size_t i = 0; i < len; i++) { + DCHECK_NE(str[i], '\0'); + this->AppendCharacter(str[i]); + } +} + +void Log::MessageBuilder::AppendCharacter(char c) { + OFStream& os = log_->os_; + // A log entry (separate by commas) cannot contain commas or line-breaks. + if (c >= 32 && c <= 126) { + if (c == ',') { + // Escape commas (log field separator) directly. + os << "\x2c"; } else { - DCHECK(c <= 0xffff); - int length = v8::internal::SNPrintF(buffer, "\\x%02x", c); - DCHECK_EQ(4, length); - log_->WriteToFile(buffer.start(), length); + // Directly append any printable ascii character. + os << c; } + } else if (c == '\n') { + os << "\\n"; + } else { + // Escape any non-printable characters. + Append("\\x%02x", c); } } -void Log::MessageBuilder::AppendUnbufferedChar(char c) { - log_->WriteToFile(&c, 1); +void Log::MessageBuilder::WriteToLogFile() { log_->os_ << std::endl; } + +template <> +Log::MessageBuilder& Log::MessageBuilder::operator<<<const char*>( + const char* string) { + this->AppendString(string); + return *this; } -void Log::MessageBuilder::AppendUnbufferedCString(const char* str) { - log_->WriteToFile(str, static_cast<int>(strlen(str))); +template <> +Log::MessageBuilder& Log::MessageBuilder::operator<<<void*>(void* pointer) { + OFStream& os = log_->os_; + // Manually format the pointer since on Windows we do not consistently + // get a "0x" prefix. + os << "0x" << std::hex << reinterpret_cast<intptr_t>(pointer) << std::dec; + return *this; } -void Log::MessageBuilder::AppendStringPart(const char* str, int len) { - if (pos_ + len > Log::kMessageBufferSize) { - len = Log::kMessageBufferSize - pos_; - DCHECK(len >= 0); - if (len == 0) return; - } - Vector<char> buf(log_->message_buffer_ + pos_, - Log::kMessageBufferSize - pos_); - StrNCpy(buf, str, len); - pos_ += len; - DCHECK(pos_ <= Log::kMessageBufferSize); +template <> +Log::MessageBuilder& Log::MessageBuilder::operator<<<char>(char c) { + this->AppendCharacter(c); + return *this; +} + +template <> +Log::MessageBuilder& Log::MessageBuilder::operator<<<String*>(String* string) { + this->AppendString(string); + return *this; +} + +template <> +Log::MessageBuilder& Log::MessageBuilder::operator<<<Symbol*>(Symbol* symbol) { + this->AppendSymbolName(symbol); + return *this; } -void Log::MessageBuilder::WriteToLogFile() { - DCHECK(pos_ <= Log::kMessageBufferSize); - // Assert that we do not already have a new line at the end. - DCHECK(pos_ == 0 || log_->message_buffer_[pos_ - 1] != '\n'); - if (pos_ == Log::kMessageBufferSize) pos_--; - log_->message_buffer_[pos_++] = '\n'; - const int written = log_->WriteToFile(log_->message_buffer_, pos_); - if (written != pos_) { - log_->stop(); - log_->logger_->LogFailure(); +template <> +Log::MessageBuilder& Log::MessageBuilder::operator<<<Name*>(Name* name) { + if (name->IsString()) { + this->AppendString(String::cast(name)); + } else { + this->AppendSymbolName(Symbol::cast(name)); } + return *this; +} + +template <> +Log::MessageBuilder& Log::MessageBuilder::operator<<<LogSeparator>( + LogSeparator separator) { + log_->os_ << ','; + return *this; } } // namespace internal |