summaryrefslogtreecommitdiff
path: root/deps/v8/src/log-utils.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/log-utils.cc')
-rw-r--r--deps/v8/src/log-utils.cc322
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