blob: c94d07a9f29220fab5caeb252381c35821f6970c [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2009 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/log-utils.h"
8#include "src/string-stream.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00009
10namespace v8 {
11namespace internal {
12
Steve Blocka7e24c12009-10-30 11:49:00 +000013
Ben Murdoch69a99ed2011-11-30 16:03:39 +000014const char* const Log::kLogToTemporaryFile = "&";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015const char* const Log::kLogToConsole = "-";
Steve Blocka7e24c12009-10-30 11:49:00 +000016
17
Steve Block44f0eee2011-05-26 01:26:41 +010018Log::Log(Logger* logger)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000019 : is_stopped_(false),
Steve Block44f0eee2011-05-26 01:26:41 +010020 output_handle_(NULL),
Steve Block44f0eee2011-05-26 01:26:41 +010021 message_buffer_(NULL),
22 logger_(logger) {
23}
Steve Blocka7e24c12009-10-30 11:49:00 +000024
25
Ben Murdochb8a8cc12014-11-26 15:28:44 +000026void Log::Initialize(const char* log_file_name) {
Steve Blocka7e24c12009-10-30 11:49:00 +000027 message_buffer_ = NewArray<char>(kMessageBufferSize);
Steve Block44f0eee2011-05-26 01:26:41 +010028
29 // --log-all enables all the log flags.
30 if (FLAG_log_all) {
Steve Block44f0eee2011-05-26 01:26:41 +010031 FLAG_log_api = true;
32 FLAG_log_code = true;
33 FLAG_log_gc = true;
34 FLAG_log_suspect = true;
35 FLAG_log_handles = true;
36 FLAG_log_regexp = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037 FLAG_log_internal_timer_events = true;
Steve Block44f0eee2011-05-26 01:26:41 +010038 }
39
40 // --prof implies --log-code.
41 if (FLAG_prof) FLAG_log_code = true;
42
Steve Block44f0eee2011-05-26 01:26:41 +010043 // If we're logging anything, we need to open the log file.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 if (Log::InitLogAtStart()) {
45 if (strcmp(log_file_name, kLogToConsole) == 0) {
Steve Block44f0eee2011-05-26 01:26:41 +010046 OpenStdout();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047 } else if (strcmp(log_file_name, kLogToTemporaryFile) == 0) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000048 OpenTemporaryFile();
49 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050 OpenFile(log_file_name);
Steve Block44f0eee2011-05-26 01:26:41 +010051 }
52 }
Steve Blocka7e24c12009-10-30 11:49:00 +000053}
54
55
56void Log::OpenStdout() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057 DCHECK(!IsEnabled());
Steve Blocka7e24c12009-10-30 11:49:00 +000058 output_handle_ = stdout;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000059}
60
61
62void Log::OpenTemporaryFile() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063 DCHECK(!IsEnabled());
64 output_handle_ = base::OS::OpenTemporaryFile();
Steve Blocka7e24c12009-10-30 11:49:00 +000065}
66
67
68void Log::OpenFile(const char* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 DCHECK(!IsEnabled());
70 output_handle_ = base::OS::FOpen(name, base::OS::LogFileOpenMode);
Steve Blocka7e24c12009-10-30 11:49:00 +000071}
72
73
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000074FILE* Log::Close() {
75 FILE* result = NULL;
76 if (output_handle_ != NULL) {
77 if (strcmp(FLAG_logfile, kLogToTemporaryFile) != 0) {
78 fclose(output_handle_);
79 } else {
80 result = output_handle_;
81 }
Steve Blocka7e24c12009-10-30 11:49:00 +000082 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000083 output_handle_ = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +000084
85 DeleteArray(message_buffer_);
86 message_buffer_ = NULL;
87
Steve Blocka7e24c12009-10-30 11:49:00 +000088 is_stopped_ = false;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000089 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +000090}
91
92
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093Log::MessageBuilder::MessageBuilder(Log* log)
94 : log_(log),
95 lock_guard_(&log_->mutex_),
Steve Block44f0eee2011-05-26 01:26:41 +010096 pos_(0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000097 DCHECK(log_->message_buffer_ != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +000098}
99
100
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000101void Log::MessageBuilder::Append(const char* format, ...) {
Steve Block44f0eee2011-05-26 01:26:41 +0100102 Vector<char> buf(log_->message_buffer_ + pos_,
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 Log::kMessageBufferSize - pos_);
104 va_list args;
105 va_start(args, format);
106 AppendVA(format, args);
107 va_end(args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108 DCHECK(pos_ <= Log::kMessageBufferSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000109}
110
111
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112void Log::MessageBuilder::AppendVA(const char* format, va_list args) {
Steve Block44f0eee2011-05-26 01:26:41 +0100113 Vector<char> buf(log_->message_buffer_ + pos_,
Steve Blocka7e24c12009-10-30 11:49:00 +0000114 Log::kMessageBufferSize - pos_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115 int result = v8::internal::VSNPrintF(buf, format, args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000116
117 // Result is -1 if output was truncated.
118 if (result >= 0) {
119 pos_ += result;
120 } else {
121 pos_ = Log::kMessageBufferSize;
122 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123 DCHECK(pos_ <= Log::kMessageBufferSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000124}
125
126
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127void Log::MessageBuilder::Append(const char c) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000128 if (pos_ < Log::kMessageBufferSize) {
Steve Block44f0eee2011-05-26 01:26:41 +0100129 log_->message_buffer_[pos_++] = c;
Steve Blocka7e24c12009-10-30 11:49:00 +0000130 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000131 DCHECK(pos_ <= Log::kMessageBufferSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000132}
133
134
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000135void Log::MessageBuilder::AppendDoubleQuotedString(const char* string) {
136 Append('"');
137 for (const char* p = string; *p != '\0'; p++) {
138 if (*p == '"') {
139 Append('\\');
140 }
141 Append(*p);
142 }
143 Append('"');
144}
145
146
147void Log::MessageBuilder::Append(String* str) {
148 DisallowHeapAllocation no_gc; // Ensure string stay valid.
Steve Blocka7e24c12009-10-30 11:49:00 +0000149 int length = str->length();
150 for (int i = 0; i < length; i++) {
151 Append(static_cast<char>(str->Get(i)));
152 }
153}
154
155
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156void Log::MessageBuilder::AppendAddress(Address addr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100157 Append("0x%" V8PRIxPTR, addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000158}
159
160
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161void Log::MessageBuilder::AppendSymbolName(Symbol* symbol) {
162 DCHECK(symbol);
163 Append("symbol(");
164 if (!symbol->name()->IsUndefined()) {
165 Append("\"");
166 AppendDetailed(String::cast(symbol->name()), false);
167 Append("\" ");
168 }
169 Append("hash %x)", symbol->Hash());
170}
171
172
173void Log::MessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000174 if (str == NULL) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000175 DisallowHeapAllocation no_gc; // Ensure string stay valid.
Steve Blocka7e24c12009-10-30 11:49:00 +0000176 int len = str->length();
177 if (len > 0x1000)
178 len = 0x1000;
179 if (show_impl_info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 Append(str->IsOneByteRepresentation() ? 'a' : '2');
Steve Blocka7e24c12009-10-30 11:49:00 +0000181 if (StringShape(str).IsExternal())
182 Append('e');
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 if (StringShape(str).IsInternalized())
Steve Blocka7e24c12009-10-30 11:49:00 +0000184 Append('#');
185 Append(":%i:", str->length());
186 }
187 for (int i = 0; i < len; i++) {
188 uc32 c = str->Get(i);
189 if (c > 0xff) {
190 Append("\\u%04x", c);
191 } else if (c < 32 || c > 126) {
192 Append("\\x%02x", c);
193 } else if (c == ',') {
194 Append("\\,");
195 } else if (c == '\\') {
196 Append("\\\\");
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100197 } else if (c == '\"') {
198 Append("\"\"");
Steve Blocka7e24c12009-10-30 11:49:00 +0000199 } else {
200 Append("%lc", c);
201 }
202 }
203}
204
205
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206void Log::MessageBuilder::AppendStringPart(const char* str, int len) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000207 if (pos_ + len > Log::kMessageBufferSize) {
208 len = Log::kMessageBufferSize - pos_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 DCHECK(len >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000210 if (len == 0) return;
211 }
Steve Block44f0eee2011-05-26 01:26:41 +0100212 Vector<char> buf(log_->message_buffer_ + pos_,
Steve Blocka7e24c12009-10-30 11:49:00 +0000213 Log::kMessageBufferSize - pos_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 StrNCpy(buf, str, len);
Steve Blocka7e24c12009-10-30 11:49:00 +0000215 pos_ += len;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 DCHECK(pos_ <= Log::kMessageBufferSize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000217}
218
219
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220void Log::MessageBuilder::WriteToLogFile() {
221 DCHECK(pos_ <= Log::kMessageBufferSize);
222 // Assert that we do not already have a new line at the end.
223 DCHECK(pos_ == 0 || log_->message_buffer_[pos_ - 1] != '\n');
224 if (pos_ == Log::kMessageBufferSize) pos_--;
225 log_->message_buffer_[pos_++] = '\n';
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000226 const int written = log_->WriteToFile(log_->message_buffer_, pos_);
Steve Block44f0eee2011-05-26 01:26:41 +0100227 if (written != pos_) {
228 log_->stop();
229 log_->logger_->LogFailure();
Steve Blocka7e24c12009-10-30 11:49:00 +0000230 }
231}
232
Steve Block44f0eee2011-05-26 01:26:41 +0100233
Steve Blocka7e24c12009-10-30 11:49:00 +0000234} } // namespace v8::internal