LCOV - code coverage report
Current view: top level - src - log-utils.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 55 135 40.7 %
Date: 2017-10-20 Functions: 10 20 50.0 %

          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/version.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : 
      18             : const char* const Log::kLogToTemporaryFile = "&";
      19             : const char* const Log::kLogToConsole = "-";
      20             : 
      21       54999 : Log::Log(Logger* logger)
      22             :     : is_stopped_(false),
      23             :       output_handle_(nullptr),
      24             :       message_buffer_(nullptr),
      25       54999 :       logger_(logger) {}
      26             : 
      27       54998 : void Log::Initialize(const char* log_file_name) {
      28       54998 :   message_buffer_ = NewArray<char>(kMessageBufferSize);
      29             : 
      30             :   // --log-all enables all the log flags.
      31       54999 :   if (FLAG_log_all) {
      32           0 :     FLAG_log_api = true;
      33           0 :     FLAG_log_code = true;
      34           0 :     FLAG_log_gc = true;
      35           0 :     FLAG_log_suspect = true;
      36           0 :     FLAG_log_handles = true;
      37           0 :     FLAG_log_internal_timer_events = true;
      38             :   }
      39             : 
      40             :   // --prof implies --log-code.
      41       54999 :   if (FLAG_prof) FLAG_log_code = true;
      42             : 
      43             :   // If we're logging anything, we need to open the log file.
      44       54999 :   if (Log::InitLogAtStart()) {
      45          21 :     if (strcmp(log_file_name, kLogToConsole) == 0) {
      46             :       OpenStdout();
      47          21 :     } else if (strcmp(log_file_name, kLogToTemporaryFile) == 0) {
      48             :       OpenTemporaryFile();
      49             :     } else {
      50             :       OpenFile(log_file_name);
      51             :     }
      52             : 
      53          21 :     if (output_handle_ != nullptr) {
      54             :       Log::MessageBuilder msg(this);
      55          21 :       if (strlen(Version::GetEmbedder()) == 0) {
      56             :         msg.Append("v8-version,%d,%d,%d,%d,%d", Version::GetMajor(),
      57             :                    Version::GetMinor(), Version::GetBuild(),
      58          42 :                    Version::GetPatch(), Version::IsCandidate());
      59             :       } else {
      60             :         msg.Append("v8-version,%d,%d,%d,%d,%s,%d", Version::GetMajor(),
      61             :                    Version::GetMinor(), Version::GetBuild(),
      62             :                    Version::GetPatch(), Version::GetEmbedder(),
      63           0 :                    Version::IsCandidate());
      64             :       }
      65          21 :       msg.WriteToLogFile();
      66             :     }
      67             :   }
      68       54998 : }
      69             : 
      70             : 
      71           0 : void Log::OpenStdout() {
      72             :   DCHECK(!IsEnabled());
      73           0 :   output_handle_ = stdout;
      74           0 : }
      75             : 
      76             : 
      77           0 : void Log::OpenTemporaryFile() {
      78             :   DCHECK(!IsEnabled());
      79          21 :   output_handle_ = base::OS::OpenTemporaryFile();
      80           0 : }
      81             : 
      82             : 
      83           0 : void Log::OpenFile(const char* name) {
      84             :   DCHECK(!IsEnabled());
      85           0 :   output_handle_ = base::OS::FOpen(name, base::OS::LogFileOpenMode);
      86           0 : }
      87             : 
      88       53365 : FILE* Log::Close() {
      89             :   FILE* result = nullptr;
      90       53365 :   if (output_handle_ != nullptr) {
      91          21 :     if (strcmp(FLAG_logfile, kLogToTemporaryFile) != 0) {
      92           0 :       fclose(output_handle_);
      93             :     } else {
      94             :       result = output_handle_;
      95             :     }
      96             :   }
      97       53365 :   output_handle_ = nullptr;
      98             : 
      99       53365 :   DeleteArray(message_buffer_);
     100       53365 :   message_buffer_ = nullptr;
     101             : 
     102       53365 :   is_stopped_ = false;
     103       53365 :   return result;
     104             : }
     105             : 
     106             : 
     107       37997 : Log::MessageBuilder::MessageBuilder(Log* log)
     108             :   : log_(log),
     109             :     lock_guard_(&log_->mutex_),
     110       76036 :     pos_(0) {
     111             :   DCHECK_NOT_NULL(log_->message_buffer_);
     112       37997 : }
     113             : 
     114             : 
     115      200852 : void Log::MessageBuilder::Append(const char* format, ...) {
     116             :   Vector<char> buf(log_->message_buffer_ + pos_,
     117             :                    Log::kMessageBufferSize - pos_);
     118             :   va_list args;
     119      200852 :   va_start(args, format);
     120      200852 :   AppendVA(format, args);
     121      200852 :   va_end(args);
     122             :   DCHECK_LE(pos_, Log::kMessageBufferSize);
     123      200852 : }
     124             : 
     125             : 
     126      200852 : void Log::MessageBuilder::AppendVA(const char* format, va_list args) {
     127             :   Vector<char> buf(log_->message_buffer_ + pos_,
     128      200852 :                    Log::kMessageBufferSize - pos_);
     129      200852 :   int result = v8::internal::VSNPrintF(buf, format, args);
     130             : 
     131             :   // Result is -1 if output was truncated.
     132      200852 :   if (result >= 0) {
     133      200852 :     pos_ += result;
     134             :   } else {
     135           0 :     pos_ = Log::kMessageBufferSize;
     136             :   }
     137             :   DCHECK_LE(pos_, Log::kMessageBufferSize);
     138      200852 : }
     139             : 
     140             : 
     141       16451 : void Log::MessageBuilder::Append(const char c) {
     142      461435 :   if (pos_ < Log::kMessageBufferSize) {
     143      461435 :     log_->message_buffer_[pos_++] = c;
     144             :   }
     145             :   DCHECK_LE(pos_, Log::kMessageBufferSize);
     146       16451 : }
     147             : 
     148             : 
     149       20247 : void Log::MessageBuilder::AppendDoubleQuotedString(const char* string) {
     150             :   Append('"');
     151      424737 :   for (const char* p = string; *p != '\0'; p++) {
     152      404490 :     if (*p == '"') {
     153             :       Append('\\');
     154             :     }
     155      404490 :     Append(*p);
     156             :   }
     157             :   Append('"');
     158       20247 : }
     159             : 
     160             : 
     161           0 : void Log::MessageBuilder::Append(String* str) {
     162             :   DisallowHeapAllocation no_gc;  // Ensure string stay valid.
     163             :   int length = str->length();
     164           0 :   for (int i = 0; i < length; i++) {
     165           0 :     Append(static_cast<char>(str->Get(i)));
     166             :   }
     167           0 : }
     168             : 
     169       54224 : void Log::MessageBuilder::AppendAddress(Address addr) {
     170       54224 :   Append("0x%" V8PRIxPTR, reinterpret_cast<intptr_t>(addr));
     171       54224 : }
     172             : 
     173           0 : void Log::MessageBuilder::AppendSymbolName(Symbol* symbol) {
     174             :   DCHECK(symbol);
     175           0 :   Append("symbol(");
     176           0 :   if (!symbol->name()->IsUndefined(symbol->GetIsolate())) {
     177           0 :     Append("\"");
     178           0 :     AppendDetailed(String::cast(symbol->name()), false);
     179           0 :     Append("\" ");
     180             :   }
     181           0 :   Append("hash %x)", symbol->Hash());
     182           0 : }
     183             : 
     184             : 
     185           0 : void Log::MessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
     186           0 :   if (str == nullptr) return;
     187             :   DisallowHeapAllocation no_gc;  // Ensure string stay valid.
     188             :   int len = str->length();
     189           0 :   if (len > 0x1000)
     190             :     len = 0x1000;
     191           0 :   if (show_impl_info) {
     192           0 :     Append(str->IsOneByteRepresentation() ? 'a' : '2');
     193           0 :     if (StringShape(str).IsExternal())
     194             :       Append('e');
     195           0 :     if (StringShape(str).IsInternalized())
     196             :       Append('#');
     197           0 :     Append(":%i:", str->length());
     198             :   }
     199           0 :   for (int i = 0; i < len; i++) {
     200           0 :     uc32 c = str->Get(i);
     201           0 :     if (c > 0xff) {
     202           0 :       Append("\\u%04x", c);
     203           0 :     } else if (c < 32 || c > 126) {
     204           0 :       Append("\\x%02x", c);
     205           0 :     } else if (c == ',') {
     206           0 :       Append("\\,");
     207           0 :     } else if (c == '\\') {
     208           0 :       Append("\\\\");
     209           0 :     } else if (c == '\"') {
     210           0 :       Append("\"\"");
     211             :     } else {
     212           0 :       Append("%lc", c);
     213             :     }
     214             :   }
     215             : }
     216             : 
     217           0 : void Log::MessageBuilder::AppendUnbufferedHeapString(String* str) {
     218           0 :   if (str == nullptr) return;
     219             :   DisallowHeapAllocation no_gc;  // Ensure string stay valid.
     220             :   ScopedVector<char> buffer(16);
     221             :   int len = str->length();
     222           0 :   for (int i = 0; i < len; i++) {
     223           0 :     uc32 c = str->Get(i);
     224           0 :     if (c >= 32 && c <= 126) {
     225           0 :       if (c == '\"') {
     226           0 :         AppendUnbufferedCString("\"\"");
     227           0 :       } else if (c == '\\') {
     228           0 :         AppendUnbufferedCString("\\\\");
     229             :       } else {
     230           0 :         AppendUnbufferedChar(c);
     231             :       }
     232           0 :     } else if (c > 0xff) {
     233           0 :       int length = v8::internal::SNPrintF(buffer, "\\u%04x", c);
     234             :       DCHECK_EQ(6, length);
     235           0 :       log_->WriteToFile(buffer.start(), length);
     236             :     } else {
     237             :       DCHECK_LE(c, 0xffff);
     238           0 :       int length = v8::internal::SNPrintF(buffer, "\\x%02x", c);
     239             :       DCHECK_EQ(4, length);
     240           0 :       log_->WriteToFile(buffer.start(), length);
     241             :     }
     242             :   }
     243             : }
     244             : 
     245           0 : void Log::MessageBuilder::AppendUnbufferedChar(char c) {
     246           0 :   log_->WriteToFile(&c, 1);
     247           0 : }
     248             : 
     249           0 : void Log::MessageBuilder::AppendUnbufferedCString(const char* str) {
     250           0 :   log_->WriteToFile(str, static_cast<int>(strlen(str)));
     251           0 : }
     252             : 
     253           0 : void Log::MessageBuilder::AppendStringPart(const char* str, int len) {
     254           0 :   if (pos_ + len > Log::kMessageBufferSize) {
     255           0 :     len = Log::kMessageBufferSize - pos_;
     256             :     DCHECK_GE(len, 0);
     257           0 :     if (len == 0) return;
     258             :   }
     259             :   Vector<char> buf(log_->message_buffer_ + pos_,
     260           0 :                    Log::kMessageBufferSize - pos_);
     261           0 :   StrNCpy(buf, str, len);
     262           0 :   pos_ += len;
     263             :   DCHECK_LE(pos_, Log::kMessageBufferSize);
     264             : }
     265             : 
     266       38018 : void Log::MessageBuilder::WriteToLogFile() {
     267             :   DCHECK_LE(pos_, Log::kMessageBufferSize);
     268             :   // Assert that we do not already have a new line at the end.
     269             :   DCHECK(pos_ == 0 || log_->message_buffer_[pos_ - 1] != '\n');
     270       38018 :   if (pos_ == Log::kMessageBufferSize) pos_--;
     271       76036 :   log_->message_buffer_[pos_++] = '\n';
     272       38018 :   const int written = log_->WriteToFile(log_->message_buffer_, pos_);
     273       38018 :   if (written != pos_) {
     274           0 :     log_->stop();
     275           0 :     log_->logger_->LogFailure();
     276             :   }
     277       38018 : }
     278             : 
     279             : }  // namespace internal
     280             : }  // namespace v8

Generated by: LCOV version 1.10