LCOV - code coverage report
Current view: top level - src - log-utils.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 102 123 82.9 %
Date: 2019-03-21 Functions: 19 24 79.2 %

          Line data    Source code
       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             : 
       5             : #include "src/log-utils.h"
       6             : 
       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"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : 
      19             : const char* const Log::kLogToTemporaryFile = "&";
      20             : const char* const Log::kLogToConsole = "-";
      21             : 
      22             : // static
      23       61534 : FILE* Log::CreateOutputHandle(const char* file_name) {
      24             :   // If we're logging anything, we need to open the log file.
      25       61534 :   if (!Log::InitLogAtStart()) {
      26             :     return nullptr;
      27          59 :   } else if (strcmp(file_name, kLogToConsole) == 0) {
      28           0 :     return stdout;
      29          59 :   } else if (strcmp(file_name, kLogToTemporaryFile) == 0) {
      30          59 :     return base::OS::OpenTemporaryFile();
      31             :   } else {
      32           0 :     return base::OS::FOpen(file_name, base::OS::LogFileOpenMode);
      33             :   }
      34             : }
      35             : 
      36       61534 : Log::Log(Logger* logger, const char* file_name)
      37             :     : is_stopped_(false),
      38       61534 :       output_handle_(Log::CreateOutputHandle(file_name)),
      39             :       os_(output_handle_ == nullptr ? stdout : output_handle_),
      40       61533 :       format_buffer_(NewArray<char>(kMessageBufferSize)),
      41      184601 :       logger_(logger) {
      42             :   // --log-all enables all the log flags.
      43       61534 :   if (FLAG_log_all) {
      44           5 :     FLAG_log_api = true;
      45           5 :     FLAG_log_code = true;
      46           5 :     FLAG_log_suspect = true;
      47           5 :     FLAG_log_handles = true;
      48           5 :     FLAG_log_internal_timer_events = true;
      49           5 :     FLAG_log_function_events = true;
      50             :   }
      51             : 
      52             :   // --prof implies --log-code.
      53       61534 :   if (FLAG_prof) FLAG_log_code = true;
      54             : 
      55      123009 :   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          59 :   if (strlen(Version::GetEmbedder()) != 0) {
      62             :     msg << kNext << Version::GetEmbedder();
      63             :   }
      64             :   msg << kNext << Version::IsCandidate();
      65             :   msg.WriteToLogFile();
      66             : }
      67             : 
      68       61517 : FILE* Log::Close() {
      69             :   FILE* result = nullptr;
      70       61517 :   if (output_handle_ != nullptr) {
      71          59 :     if (strcmp(FLAG_logfile, kLogToTemporaryFile) != 0) {
      72           0 :       fclose(output_handle_);
      73             :     } else {
      74             :       result = output_handle_;
      75             :     }
      76             :   }
      77       61517 :   output_handle_ = nullptr;
      78             : 
      79       61517 :   DeleteArray(format_buffer_);
      80       61519 :   format_buffer_ = nullptr;
      81             : 
      82       61519 :   is_stopped_ = false;
      83       61519 :   return result;
      84             : }
      85             : 
      86       45990 : Log::MessageBuilder::MessageBuilder(Log* log)
      87       46049 :     : log_(log), lock_guard_(&log_->mutex_) {
      88             :   DCHECK_NOT_NULL(log_->format_buffer_);
      89       45990 : }
      90             : 
      91        5562 : void Log::MessageBuilder::AppendString(String str,
      92             :                                        base::Optional<int> length_limit) {
      93        5562 :   if (str.is_null()) return;
      94             : 
      95             :   DisallowHeapAllocation no_gc;  // Ensure string stays valid.
      96        5562 :   int length = str->length();
      97        5786 :   if (length_limit) length = std::min(length, *length_limit);
      98      150284 :   for (int i = 0; i < length; i++) {
      99             :     uint16_t c = str->Get(i);
     100       72361 :     if (c <= 0xFF) {
     101       72361 :       AppendCharacter(static_cast<char>(c));
     102             :     } else {
     103             :       // Escape non-ascii characters.
     104           0 :       AppendRawFormatString("\\u%04x", c & 0xFFFF);
     105             :     }
     106             :   }
     107             : }
     108             : 
     109           0 : void Log::MessageBuilder::AppendString(Vector<const char> str) {
     110           0 :   for (auto i = str.begin(); i < str.end(); i++) AppendCharacter(*i);
     111           0 : }
     112             : 
     113       89404 : void Log::MessageBuilder::AppendString(const char* str) {
     114       89404 :   if (str == nullptr) return;
     115       89356 :   AppendString(str, strlen(str));
     116             : }
     117             : 
     118          72 : void Log::MessageBuilder::AppendString(const char* str, size_t length) {
     119       89428 :   if (str == nullptr) return;
     120             : 
     121    30007486 :   for (size_t i = 0; i < length; i++) {
     122             :     DCHECK_NE(str[i], '\0');
     123    14959029 :     AppendCharacter(str[i]);
     124             :   }
     125             : }
     126             : 
     127         144 : void Log::MessageBuilder::AppendFormatString(const char* format, ...) {
     128             :   va_list args;
     129         144 :   va_start(args, format);
     130             :   const int length = FormatStringIntoBuffer(format, args);
     131         144 :   va_end(args);
     132        2826 :   for (int i = 0; i < length; i++) {
     133             :     DCHECK_NE(log_->format_buffer_[i], '\0');
     134        1341 :     AppendCharacter(log_->format_buffer_[i]);
     135             :   }
     136         144 : }
     137             : 
     138    15032731 : void Log::MessageBuilder::AppendCharacter(char c) {
     139    15032731 :   if (c >= 32 && c <= 126) {
     140    14725114 :     if (c == ',') {
     141             :       // Escape commas to avoid adding column separators.
     142       89723 :       AppendRawFormatString("\\x2C");
     143    14635391 :     } else if (c == '\\') {
     144           0 :       AppendRawFormatString("\\\\");
     145             :     } else {
     146             :       // Safe, printable ascii character.
     147             :       AppendRawCharacter(c);
     148             :     }
     149      307617 :   } else if (c == '\n') {
     150             :     // Escape newlines to avoid adding row separators.
     151      307617 :     AppendRawFormatString("\\n");
     152             :   } else {
     153             :     // Escape non-printable characters.
     154           0 :     AppendRawFormatString("\\x%02x", c & 0xFF);
     155             :   }
     156    15032731 : }
     157             : 
     158         253 : void Log::MessageBuilder::AppendSymbolName(Symbol symbol) {
     159             :   DCHECK(!symbol.is_null());
     160         253 :   OFStream& os = log_->os_;
     161         253 :   os << "symbol(";
     162         253 :   if (!symbol->name()->IsUndefined()) {
     163         224 :     os << "\"";
     164         224 :     AppendSymbolNameDetails(String::cast(symbol->name()), false);
     165         224 :     os << "\" ";
     166             :   }
     167         506 :   os << "hash " << std::hex << symbol->Hash() << std::dec << ")";
     168         253 : }
     169             : 
     170         224 : void Log::MessageBuilder::AppendSymbolNameDetails(String str,
     171             :                                                   bool show_impl_info) {
     172         224 :   if (str.is_null()) return;
     173             : 
     174             :   DisallowHeapAllocation no_gc;  // Ensure string stays valid.
     175         224 :   OFStream& os = log_->os_;
     176             :   int limit = str->length();
     177         224 :   if (limit > 0x1000) limit = 0x1000;
     178         224 :   if (show_impl_info) {
     179           0 :     os << (str->IsOneByteRepresentation() ? 'a' : '2');
     180           0 :     if (StringShape(str).IsExternal()) os << 'e';
     181           0 :     if (StringShape(str).IsInternalized()) os << '#';
     182           0 :     os << ':' << str->length() << ':';
     183             :   }
     184         224 :   AppendString(str, limit);
     185             : }
     186             : 
     187           0 : int Log::MessageBuilder::FormatStringIntoBuffer(const char* format,
     188             :                                                 va_list args) {
     189      397484 :   Vector<char> buf(log_->format_buffer_, Log::kMessageBufferSize);
     190      397484 :   int length = v8::internal::VSNPrintF(buf, format, args);
     191             :   // |length| is -1 if output was truncated.
     192      397484 :   if (length == -1) length = Log::kMessageBufferSize;
     193             :   DCHECK_LE(length, Log::kMessageBufferSize);
     194             :   DCHECK_GE(length, 0);
     195           0 :   return length;
     196             : }
     197             : 
     198      397340 : void Log::MessageBuilder::AppendRawFormatString(const char* format, ...) {
     199             :   va_list args;
     200      397340 :   va_start(args, format);
     201             :   const int length = FormatStringIntoBuffer(format, args);
     202      397340 :   va_end(args);
     203     2345592 :   for (int i = 0; i < length; i++) {
     204             :     DCHECK_NE(log_->format_buffer_[i], '\0');
     205      974126 :     AppendRawCharacter(log_->format_buffer_[i]);
     206             :   }
     207      397340 : }
     208             : 
     209    15791452 : void Log::MessageBuilder::AppendRawCharacter(char c) { log_->os_ << c; }
     210             : 
     211       92039 : void Log::MessageBuilder::WriteToLogFile() { log_->os_ << std::endl; }
     212             : 
     213             : template <>
     214       89345 : Log::MessageBuilder& Log::MessageBuilder::operator<<<const char*>(
     215             :     const char* string) {
     216       89404 :   this->AppendString(string);
     217       89345 :   return *this;
     218             : }
     219             : 
     220             : template <>
     221        6734 : Log::MessageBuilder& Log::MessageBuilder::operator<<<void*>(void* pointer) {
     222        6734 :   OFStream& os = log_->os_;
     223             :   // Manually format the pointer since on Windows we do not consistently
     224             :   // get a "0x" prefix.
     225        6734 :   os << "0x" << std::hex << reinterpret_cast<intptr_t>(pointer) << std::dec;
     226        6734 :   return *this;
     227             : }
     228             : 
     229             : template <>
     230           0 : Log::MessageBuilder& Log::MessageBuilder::operator<<<char>(char c) {
     231           0 :   this->AppendCharacter(c);
     232           0 :   return *this;
     233             : }
     234             : 
     235             : template <>
     236         330 : Log::MessageBuilder& Log::MessageBuilder::operator<<<String>(String string) {
     237         330 :   this->AppendString(string);
     238         330 :   return *this;
     239             : }
     240             : 
     241             : template <>
     242           0 : Log::MessageBuilder& Log::MessageBuilder::operator<<<Symbol>(Symbol symbol) {
     243           0 :   this->AppendSymbolName(symbol);
     244           0 :   return *this;
     245             : }
     246             : 
     247             : template <>
     248        5261 : Log::MessageBuilder& Log::MessageBuilder::operator<<<Name>(Name name) {
     249        5261 :   if (name->IsString()) {
     250        5008 :     this->AppendString(String::cast(name));
     251             :   } else {
     252         253 :     this->AppendSymbolName(Symbol::cast(name));
     253             :   }
     254        5261 :   return *this;
     255             : }
     256             : 
     257             : template <>
     258      181640 : Log::MessageBuilder& Log::MessageBuilder::operator<<<LogSeparator>(
     259             :     LogSeparator separator) {
     260             :   // Skip escaping to create a new column.
     261             :   this->AppendRawCharacter(',');
     262      181640 :   return *this;
     263             : }
     264             : 
     265             : }  // namespace internal
     266      120216 : }  // namespace v8

Generated by: LCOV version 1.10