1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "log-utils.h"
3144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "string-stream.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochconst char* const Log::kLogToTemporaryFile = "&";
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockLog::Log(Logger* logger)
413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  : is_stopped_(false),
4244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    output_handle_(NULL),
43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ll_output_handle_(NULL),
4444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    mutex_(NULL),
4544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    message_buffer_(NULL),
4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    logger_(logger) {
4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void AddIsolateIdIfNeeded(StringStream* stream) {
5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (isolate->IsDefaultIsolate()) return;
5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  stream->Add("isolate-%p-", isolate);
5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Log::Initialize() {
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mutex_ = OS::CreateMutex();
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_buffer_ = NewArray<char>(kMessageBufferSize);
6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // --log-all enables all the log flags.
6244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_log_all) {
6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    FLAG_log_runtime = true;
6444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    FLAG_log_api = true;
6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    FLAG_log_code = true;
6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    FLAG_log_gc = true;
6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    FLAG_log_suspect = true;
6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    FLAG_log_handles = true;
6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    FLAG_log_regexp = true;
7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // --prof implies --log-code.
7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_prof) FLAG_log_code = true;
7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // --prof_lazy controls --log-code, implies --noprof_auto.
7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (FLAG_prof_lazy) {
7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    FLAG_log_code = false;
7844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    FLAG_prof_auto = false;
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool open_log_file = FLAG_log || FLAG_log_runtime || FLAG_log_api
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      || FLAG_log_code || FLAG_log_gc || FLAG_log_handles || FLAG_log_suspect
83257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      || FLAG_log_regexp || FLAG_log_state_changes || FLAG_ll_prof;
8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If we're logging anything, we need to open the log file.
8644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (open_log_file) {
8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (strcmp(FLAG_logfile, "-") == 0) {
8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      OpenStdout();
893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else if (strcmp(FLAG_logfile, kLogToTemporaryFile) == 0) {
903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      OpenTemporaryFile();
913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (strchr(FLAG_logfile, '%') != NULL ||
9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          !Isolate::Current()->IsDefaultIsolate()) {
9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // If there's a '%' in the log file name we have to expand
9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        // placeholders.
9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HeapStringAllocator allocator;
9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        StringStream stream(&allocator);
9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        AddIsolateIdIfNeeded(&stream);
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        for (const char* p = FLAG_logfile; *p; p++) {
10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          if (*p == '%') {
10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            p++;
10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            switch (*p) {
10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              case '\0':
10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                // If there's a % at the end of the string we back up
10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                // one character so we can escape the loop properly.
10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                p--;
10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                break;
10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              case 't': {
10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                // %t expands to the current time in milliseconds.
11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                double time = OS::TimeCurrentMillis();
11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                stream.Add("%.0f", FmtElm(time));
11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                break;
11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block              }
11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block              case '%':
11544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                // %% expands (contracts really) to %.
11644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                stream.Put('%');
11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                break;
11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              default:
11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                // All other %'s expand to themselves.
12044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                stream.Put('%');
12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                stream.Put(*p);
12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                break;
12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            }
12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          } else {
12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            stream.Put(*p);
12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          }
12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        }
128589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        SmartArrayPointer<const char> expanded = stream.ToCString();
12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        OpenFile(*expanded);
13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else {
13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        OpenFile(FLAG_logfile);
13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Log::OpenStdout() {
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!IsEnabled());
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  output_handle_ = stdout;
1413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
1423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Log::OpenTemporaryFile() {
1453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!IsEnabled());
1463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  output_handle_ = i::OS::OpenTemporaryFile();
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Extension added to V8 log file name to get the low-level log name.
151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const char kLowLevelLogExt[] = ".ll";
152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// File buffer size of the low-level log. We don't use the default to
154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// minimize the associated overhead.
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kLowLevelLogBufferSize = 2 * MB;
156f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
157f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Log::OpenFile(const char* name) {
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!IsEnabled());
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  output_handle_ = OS::FOpen(name, OS::LogFileOpenMode);
161f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (FLAG_ll_prof) {
162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Open the low-level log file.
163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    size_t len = strlen(name);
164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ScopedVector<char> ll_name(static_cast<int>(len + sizeof(kLowLevelLogExt)));
165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    memcpy(ll_name.start(), name, len);
166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    memcpy(ll_name.start() + len, kLowLevelLogExt, sizeof(kLowLevelLogExt));
167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ll_output_handle_ = OS::FOpen(ll_name.start(), OS::LogFileOpenMode);
168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    setvbuf(ll_output_handle_, NULL, _IOFBF, kLowLevelLogBufferSize);
169f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1733fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochFILE* Log::Close() {
1743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  FILE* result = NULL;
1753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (output_handle_ != NULL) {
1763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (strcmp(FLAG_logfile, kLogToTemporaryFile) != 0) {
1773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      fclose(output_handle_);
1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
1793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result = output_handle_;
1803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  output_handle_ = NULL;
1833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (ll_output_handle_ != NULL) fclose(ll_output_handle_);
1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ll_output_handle_ = NULL;
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DeleteArray(message_buffer_);
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  message_buffer_ = NULL;
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  delete mutex_;
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mutex_ = NULL;
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  is_stopped_ = false;
1933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return result;
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockLogMessageBuilder::LogMessageBuilder(Logger* logger)
19844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  : log_(logger->log_),
19944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    sl(log_->mutex_),
20044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    pos_(0) {
20144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(log_->message_buffer_ != NULL);
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LogMessageBuilder::Append(const char* format, ...) {
20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Vector<char> buf(log_->message_buffer_ + pos_,
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   Log::kMessageBufferSize - pos_);
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_list args;
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_start(args, format);
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AppendVA(format, args);
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  va_end(args);
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pos_ <= Log::kMessageBufferSize);
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LogMessageBuilder::AppendVA(const char* format, va_list args) {
21744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Vector<char> buf(log_->message_buffer_ + pos_,
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   Log::kMessageBufferSize - pos_);
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int result = v8::internal::OS::VSNPrintF(buf, format, args);
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Result is -1 if output was truncated.
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (result >= 0) {
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pos_ += result;
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pos_ = Log::kMessageBufferSize;
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pos_ <= Log::kMessageBufferSize);
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LogMessageBuilder::Append(const char c) {
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pos_ < Log::kMessageBufferSize) {
23344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    log_->message_buffer_[pos_++] = c;
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pos_ <= Log::kMessageBufferSize);
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LogMessageBuilder::Append(String* str) {
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AssertNoAllocation no_heap_allocation;  // Ensure string stay valid.
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int length = str->length();
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < length; i++) {
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Append(static_cast<char>(str->Get(i)));
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LogMessageBuilder::AppendAddress(Address addr) {
249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Append("0x%" V8PRIxPTR, addr);
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (str == NULL) return;
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AssertNoAllocation no_heap_allocation;  // Ensure string stay valid.
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int len = str->length();
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (len > 0x1000)
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    len = 0x1000;
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (show_impl_info) {
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Append(str->IsAsciiRepresentation() ? 'a' : '2');
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (StringShape(str).IsExternal())
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Append('e');
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (StringShape(str).IsSymbol())
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Append('#');
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Append(":%i:", str->length());
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < len; i++) {
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc32 c = str->Get(i);
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (c > 0xff) {
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Append("\\u%04x", c);
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (c < 32 || c > 126) {
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Append("\\x%02x", c);
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (c == ',') {
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Append("\\,");
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (c == '\\') {
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Append("\\\\");
277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else if (c == '\"') {
278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Append("\"\"");
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Append("%lc", c);
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LogMessageBuilder::AppendStringPart(const char* str, int len) {
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pos_ + len > Log::kMessageBufferSize) {
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    len = Log::kMessageBufferSize - pos_;
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(len >= 0);
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (len == 0) return;
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
29244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Vector<char> buf(log_->message_buffer_ + pos_,
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   Log::kMessageBufferSize - pos_);
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  OS::StrNCpy(buf, str, len);
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pos_ += len;
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pos_ <= Log::kMessageBufferSize);
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid LogMessageBuilder::WriteToLogFile() {
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(pos_ <= Log::kMessageBufferSize);
3023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int written = log_->WriteToFile(log_->message_buffer_, pos_);
30344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (written != pos_) {
30444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    log_->stop();
30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    log_->logger_->LogFailure();
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
311