blob: dedf7e90c5c6ada2622a943d8f1e191ace44face [file] [log] [blame]
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdarg.h>
29
30#include "v8.h"
31
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +000032#include "bootstrapper.h"
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000033#include "code-stubs.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000034#include "deoptimizer.h"
ager@chromium.org01beca72009-11-24 14:29:16 +000035#include "global-handles.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036#include "log.h"
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000037#include "macro-assembler.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000038#include "runtime-profiler.h"
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +000039#include "serialize.h"
40#include "string-stream.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000041#include "vm-state-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000042
kasperl@chromium.org71affb52009-05-26 05:44:31 +000043namespace v8 {
44namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000047// Sliding state window. Updates counters to keep track of the last
48// window of kBufferSize states. This is useful to track where we
49// spent our time.
50//
51class SlidingStateWindow {
52 public:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000053 explicit SlidingStateWindow(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000054 ~SlidingStateWindow();
55 void AddState(StateTag state);
56
57 private:
58 static const int kBufferSize = 256;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000059 Counters* counters_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000060 int current_index_;
61 bool is_full_;
62 byte buffer_[kBufferSize];
63
64
65 void IncrementStateCounter(StateTag state) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000066 counters_->state_counters(state)->Increment();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000067 }
68
69
70 void DecrementStateCounter(StateTag state) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000071 counters_->state_counters(state)->Decrement();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000072 }
73};
74
75
76//
77// The Profiler samples pc and sp values for the main thread.
78// Each sample is appended to a circular buffer.
79// An independent thread removes data and writes it to the log.
80// This design minimizes the time spent in the sampler.
81//
82class Profiler: public Thread {
83 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000084 explicit Profiler(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000085 void Engage();
86 void Disengage();
87
88 // Inserts collected profiling data into buffer.
89 void Insert(TickSample* sample) {
iposva@chromium.org245aa852009-02-10 00:49:54 +000090 if (paused_)
91 return;
92
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000093 if (Succ(head_) == tail_) {
94 overflow_ = true;
95 } else {
96 buffer_[head_] = *sample;
97 head_ = Succ(head_);
98 buffer_semaphore_->Signal(); // Tell we have an element.
99 }
100 }
101
102 // Waits for a signal and removes profiling data.
103 bool Remove(TickSample* sample) {
104 buffer_semaphore_->Wait(); // Wait for an element.
105 *sample = buffer_[tail_];
106 bool result = overflow_;
107 tail_ = Succ(tail_);
108 overflow_ = false;
109 return result;
110 }
111
112 void Run();
113
iposva@chromium.org245aa852009-02-10 00:49:54 +0000114 // Pause and Resume TickSample data collection.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000115 bool paused() const { return paused_; }
116 void pause() { paused_ = true; }
117 void resume() { paused_ = false; }
iposva@chromium.org245aa852009-02-10 00:49:54 +0000118
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000119 private:
120 // Returns the next index in the cyclic buffer.
121 int Succ(int index) { return (index + 1) % kBufferSize; }
122
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000123 Isolate* isolate_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124 // Cyclic buffer for communicating profiling samples
125 // between the signal handler and the worker thread.
126 static const int kBufferSize = 128;
127 TickSample buffer_[kBufferSize]; // Buffer storage.
128 int head_; // Index to the buffer head.
129 int tail_; // Index to the buffer tail.
130 bool overflow_; // Tell whether a buffer overflow has occurred.
131 Semaphore* buffer_semaphore_; // Sempahore used for buffer synchronization.
132
ager@chromium.org3811b432009-10-28 14:53:37 +0000133 // Tells whether profiler is engaged, that is, processing thread is stated.
134 bool engaged_;
135
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000136 // Tells whether worker thread should continue running.
137 bool running_;
iposva@chromium.org245aa852009-02-10 00:49:54 +0000138
139 // Tells whether we are currently recording tick samples.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000140 bool paused_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000141};
142
143
144//
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000145// StackTracer implementation
146//
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000147void StackTracer::Trace(Isolate* isolate, TickSample* sample) {
148 ASSERT(isolate->IsInitialized());
149
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000150 // Avoid collecting traces while doing GC.
lrn@chromium.org25156de2010-04-06 13:10:27 +0000151 if (sample->state == GC) return;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000152
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000153 const Address js_entry_sp =
154 Isolate::js_entry_sp(isolate->thread_local_top());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000155 if (js_entry_sp == 0) {
156 // Not executing JS now.
ager@chromium.orge2902be2009-06-08 12:21:35 +0000157 return;
158 }
159
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000160 const Address callback = isolate->external_callback();
161 if (callback != NULL) {
162 sample->external_callback = callback;
163 sample->has_external_callback = true;
164 } else {
165 // Sample potential return address value for frameless invocation of
166 // stubs (we'll figure out later, if this value makes sense).
167 sample->tos = Memory::Address_at(sample->sp);
168 sample->has_external_callback = false;
ager@chromium.org01beca72009-11-24 14:29:16 +0000169 }
170
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000171 SafeStackTraceFrameIterator it(isolate,
172 sample->fp, sample->sp,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000173 sample->sp, js_entry_sp);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000174 int i = 0;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000175 while (!it.done() && i < TickSample::kMaxFramesCount) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000176 sample->stack[i++] = it.frame()->pc();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000177 it.Advance();
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000178 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000179 sample->frames_count = i;
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000180}
181
182
183//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000184// Ticker used to provide ticks to the profiler and the sliding state
185// window.
186//
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000187class Ticker: public Sampler {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188 public:
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000189 Ticker(Isolate* isolate, int interval):
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000190 Sampler(isolate, interval),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000191 window_(NULL),
192 profiler_(NULL) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000193
194 ~Ticker() { if (IsActive()) Stop(); }
195
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000196 virtual void Tick(TickSample* sample) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000197 if (profiler_) profiler_->Insert(sample);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000198 if (window_) window_->AddState(sample->state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000199 }
200
201 void SetWindow(SlidingStateWindow* window) {
202 window_ = window;
203 if (!IsActive()) Start();
204 }
205
206 void ClearWindow() {
207 window_ = NULL;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000208 if (!profiler_ && IsActive() && !RuntimeProfiler::IsEnabled()) Stop();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000209 }
210
211 void SetProfiler(Profiler* profiler) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000212 ASSERT(profiler_ == NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000213 profiler_ = profiler;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000214 IncreaseProfilingDepth();
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000215 if (!FLAG_prof_lazy && !IsActive()) Start();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216 }
217
218 void ClearProfiler() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000219 DecreaseProfilingDepth();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000220 profiler_ = NULL;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000221 if (!window_ && IsActive() && !RuntimeProfiler::IsEnabled()) Stop();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222 }
223
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000224 protected:
225 virtual void DoSampleStack(TickSample* sample) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000226 StackTracer::Trace(isolate(), sample);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000227 }
228
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229 private:
230 SlidingStateWindow* window_;
231 Profiler* profiler_;
232};
233
234
235//
236// SlidingStateWindow implementation.
237//
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000238SlidingStateWindow::SlidingStateWindow(Isolate* isolate)
239 : counters_(isolate->counters()), current_index_(0), is_full_(false) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000240 for (int i = 0; i < kBufferSize; i++) {
241 buffer_[i] = static_cast<byte>(OTHER);
242 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000243 isolate->logger()->ticker_->SetWindow(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000244}
245
246
247SlidingStateWindow::~SlidingStateWindow() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000248 LOGGER->ticker_->ClearWindow();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249}
250
251
252void SlidingStateWindow::AddState(StateTag state) {
253 if (is_full_) {
254 DecrementStateCounter(static_cast<StateTag>(buffer_[current_index_]));
255 } else if (current_index_ == kBufferSize - 1) {
256 is_full_ = true;
257 }
258 buffer_[current_index_] = static_cast<byte>(state);
259 IncrementStateCounter(state);
260 ASSERT(IsPowerOf2(kBufferSize));
261 current_index_ = (current_index_ + 1) & (kBufferSize - 1);
262}
263
264
265//
266// Profiler implementation.
267//
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000268Profiler::Profiler(Isolate* isolate)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000269 : Thread("v8:Profiler"),
270 isolate_(isolate),
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000271 head_(0),
ager@chromium.org3811b432009-10-28 14:53:37 +0000272 tail_(0),
273 overflow_(false),
274 buffer_semaphore_(OS::CreateSemaphore(0)),
275 engaged_(false),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000276 running_(false),
277 paused_(false) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000278}
279
280
281void Profiler::Engage() {
ager@chromium.org3811b432009-10-28 14:53:37 +0000282 if (engaged_) return;
283 engaged_ = true;
284
285 // TODO(mnaganov): This is actually "Chromium" mode. Flags need to be revised.
286 // http://code.google.com/p/v8/issues/detail?id=487
287 if (!FLAG_prof_lazy) {
288 OS::LogSharedLibraryAddresses();
289 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000290
291 // Start thread processing the profiler buffer.
292 running_ = true;
293 Start();
294
295 // Register to get ticks.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000296 LOGGER->ticker_->SetProfiler(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000297
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000298 LOGGER->ProfilerBeginEvent();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000299}
300
301
302void Profiler::Disengage() {
ager@chromium.org3811b432009-10-28 14:53:37 +0000303 if (!engaged_) return;
304
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305 // Stop receiving ticks.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000306 LOGGER->ticker_->ClearProfiler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000307
308 // Terminate the worker thread by setting running_ to false,
309 // inserting a fake element in the queue and then wait for
310 // the thread to terminate.
311 running_ = false;
312 TickSample sample;
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000313 // Reset 'paused_' flag, otherwise semaphore may not be signalled.
314 resume();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315 Insert(&sample);
316 Join();
317
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000318 LOG(ISOLATE, UncheckedStringEvent("profiler", "end"));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000319}
320
321
322void Profiler::Run() {
323 TickSample sample;
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000324 bool overflow = Remove(&sample);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000325 while (running_) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000326 LOG(isolate_, TickEvent(&sample, overflow));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000327 overflow = Remove(&sample);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000328 }
329}
330
331
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000332// Low-level profiling event structures.
333
334struct LowLevelCodeCreateStruct {
335 static const char kTag = 'C';
336
337 int32_t name_size;
338 Address code_address;
339 int32_t code_size;
340};
341
342
343struct LowLevelCodeMoveStruct {
344 static const char kTag = 'M';
345
346 Address from_address;
347 Address to_address;
348};
349
350
351struct LowLevelCodeDeleteStruct {
352 static const char kTag = 'D';
353
354 Address address;
355};
356
357
358struct LowLevelSnapshotPositionStruct {
359 static const char kTag = 'P';
360
361 Address address;
362 int32_t position;
363};
364
365
366static const char kCodeMovingGCTag = 'G';
367
368
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000369//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000370// Logger class implementation.
371//
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000372
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000373class Logger::NameMap {
374 public:
375 NameMap() : impl_(&PointerEquals) {}
376
377 ~NameMap() {
378 for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) {
379 DeleteArray(static_cast<const char*>(p->value));
380 }
381 }
382
383 void Insert(Address code_address, const char* name, int name_size) {
384 HashMap::Entry* entry = FindOrCreateEntry(code_address);
385 if (entry->value == NULL) {
386 entry->value = CopyName(name, name_size);
387 }
388 }
389
390 const char* Lookup(Address code_address) {
391 HashMap::Entry* entry = FindEntry(code_address);
392 return (entry != NULL) ? static_cast<const char*>(entry->value) : NULL;
393 }
394
395 void Remove(Address code_address) {
396 HashMap::Entry* entry = FindEntry(code_address);
ager@chromium.org04921a82011-06-27 13:21:41 +0000397 if (entry != NULL) {
398 DeleteArray(static_cast<char*>(entry->value));
399 RemoveEntry(entry);
400 }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000401 }
402
403 void Move(Address from, Address to) {
404 if (from == to) return;
405 HashMap::Entry* from_entry = FindEntry(from);
406 ASSERT(from_entry != NULL);
407 void* value = from_entry->value;
408 RemoveEntry(from_entry);
409 HashMap::Entry* to_entry = FindOrCreateEntry(to);
410 ASSERT(to_entry->value == NULL);
411 to_entry->value = value;
412 }
413
414 private:
415 static bool PointerEquals(void* lhs, void* rhs) {
416 return lhs == rhs;
417 }
418
419 static char* CopyName(const char* name, int name_size) {
420 char* result = NewArray<char>(name_size + 1);
421 for (int i = 0; i < name_size; ++i) {
422 char c = name[i];
423 if (c == '\0') c = ' ';
424 result[i] = c;
425 }
426 result[name_size] = '\0';
427 return result;
428 }
429
430 HashMap::Entry* FindOrCreateEntry(Address code_address) {
431 return impl_.Lookup(code_address, ComputePointerHash(code_address), true);
432 }
433
434 HashMap::Entry* FindEntry(Address code_address) {
435 return impl_.Lookup(code_address, ComputePointerHash(code_address), false);
436 }
437
438 void RemoveEntry(HashMap::Entry* entry) {
439 impl_.Remove(entry->key, entry->hash);
440 }
441
442 HashMap impl_;
443
444 DISALLOW_COPY_AND_ASSIGN(NameMap);
445};
446
447
448class Logger::NameBuffer {
449 public:
450 NameBuffer() { Reset(); }
451
452 void Reset() {
453 utf8_pos_ = 0;
454 }
455
456 void AppendString(String* str) {
457 if (str == NULL) return;
458 if (str->HasOnlyAsciiChars()) {
459 int utf8_length = Min(str->length(), kUtf8BufferSize - utf8_pos_);
460 String::WriteToFlat(str, utf8_buffer_ + utf8_pos_, 0, utf8_length);
461 utf8_pos_ += utf8_length;
462 return;
463 }
464 int uc16_length = Min(str->length(), kUc16BufferSize);
465 String::WriteToFlat(str, uc16_buffer_, 0, uc16_length);
466 for (int i = 0; i < uc16_length && utf8_pos_ < kUtf8BufferSize; ++i) {
467 uc16 c = uc16_buffer_[i];
468 if (c <= String::kMaxAsciiCharCodeU) {
469 utf8_buffer_[utf8_pos_++] = static_cast<char>(c);
470 } else {
471 int char_length = unibrow::Utf8::Length(c);
472 if (utf8_pos_ + char_length > kUtf8BufferSize) break;
473 unibrow::Utf8::Encode(utf8_buffer_ + utf8_pos_, c);
474 utf8_pos_ += char_length;
475 }
476 }
477 }
478
479 void AppendBytes(const char* bytes, int size) {
480 size = Min(size, kUtf8BufferSize - utf8_pos_);
481 memcpy(utf8_buffer_ + utf8_pos_, bytes, size);
482 utf8_pos_ += size;
483 }
484
485 void AppendBytes(const char* bytes) {
486 AppendBytes(bytes, StrLength(bytes));
487 }
488
489 void AppendByte(char c) {
490 if (utf8_pos_ >= kUtf8BufferSize) return;
491 utf8_buffer_[utf8_pos_++] = c;
492 }
493
494 void AppendInt(int n) {
495 Vector<char> buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_);
496 int size = OS::SNPrintF(buffer, "%d", n);
497 if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
498 utf8_pos_ += size;
499 }
500 }
501
502 const char* get() { return utf8_buffer_; }
503 int size() const { return utf8_pos_; }
504
505 private:
506 static const int kUtf8BufferSize = 512;
507 static const int kUc16BufferSize = 128;
508
509 int utf8_pos_;
510 char utf8_buffer_[kUtf8BufferSize];
511 uc16 uc16_buffer_[kUc16BufferSize];
512};
513
514
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000515Logger::Logger()
516 : ticker_(NULL),
517 profiler_(NULL),
518 sliding_state_window_(NULL),
519 log_events_(NULL),
520 logging_nesting_(0),
521 cpu_profiler_nesting_(0),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000522 log_(new Log(this)),
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000523 name_buffer_(new NameBuffer),
524 address_to_name_map_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000525 is_initialized_(false),
526 last_address_(NULL),
527 prev_sp_(NULL),
528 prev_function_(NULL),
529 prev_to_(NULL),
530 prev_code_(NULL) {
531}
532
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000533
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000534Logger::~Logger() {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000535 delete address_to_name_map_;
536 delete name_buffer_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000537 delete log_;
538}
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000539
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000540
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000541#define DECLARE_EVENT(ignore1, name) name,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000542static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000543 LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000544};
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000545#undef DECLARE_EVENT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000546
ager@chromium.org9085a012009-05-11 19:22:57 +0000547
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000548void Logger::ProfilerBeginEvent() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000549 if (!log_->IsEnabled()) return;
550 LogMessageBuilder msg(this);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000551 msg.Append("profiler,\"begin\",%d\n", kSamplingIntervalMs);
552 msg.WriteToLogFile();
553}
554
ager@chromium.org381abbb2009-02-25 13:23:22 +0000555
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000556void Logger::StringEvent(const char* name, const char* value) {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000557 if (FLAG_log) UncheckedStringEvent(name, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000558}
559
560
ager@chromium.org6f10e412009-02-13 10:11:16 +0000561void Logger::UncheckedStringEvent(const char* name, const char* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000562 if (!log_->IsEnabled()) return;
563 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000564 msg.Append("%s,\"%s\"\n", name, value);
565 msg.WriteToLogFile();
ager@chromium.org6f10e412009-02-13 10:11:16 +0000566}
ager@chromium.org6f10e412009-02-13 10:11:16 +0000567
568
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000569void Logger::IntEvent(const char* name, int value) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000570 if (FLAG_log) UncheckedIntEvent(name, value);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000571}
572
573
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000574void Logger::IntPtrTEvent(const char* name, intptr_t value) {
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000575 if (FLAG_log) UncheckedIntPtrTEvent(name, value);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000576}
577
578
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000579void Logger::UncheckedIntEvent(const char* name, int value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000580 if (!log_->IsEnabled()) return;
581 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000582 msg.Append("%s,%d\n", name, value);
583 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000584}
585
586
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000587void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000588 if (!log_->IsEnabled()) return;
589 LogMessageBuilder msg(this);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000590 msg.Append("%s,%" V8_PTR_PREFIX "d\n", name, value);
591 msg.WriteToLogFile();
592}
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000593
594
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000595void Logger::HandleEvent(const char* name, Object** location) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000596 if (!log_->IsEnabled() || !FLAG_log_handles) return;
597 LogMessageBuilder msg(this);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000598 msg.Append("%s,0x%" V8PRIxPTR "\n", name, location);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000599 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000600}
601
602
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000603// ApiEvent is private so all the calls come from the Logger class. It is the
ager@chromium.org9085a012009-05-11 19:22:57 +0000604// caller's responsibility to ensure that log is enabled and that
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000605// FLAG_log_api is true.
606void Logger::ApiEvent(const char* format, ...) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000607 ASSERT(log_->IsEnabled() && FLAG_log_api);
608 LogMessageBuilder msg(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000609 va_list ap;
610 va_start(ap, format);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000611 msg.AppendVA(format, ap);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000612 va_end(ap);
613 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000614}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000615
616
617void Logger::ApiNamedSecurityCheck(Object* key) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000618 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000619 if (key->IsString()) {
620 SmartPointer<char> str =
621 String::cast(key)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
622 ApiEvent("api,check-security,\"%s\"\n", *str);
623 } else if (key->IsUndefined()) {
624 ApiEvent("api,check-security,undefined\n");
625 } else {
626 ApiEvent("api,check-security,['no-name']\n");
627 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000628}
629
630
631void Logger::SharedLibraryEvent(const char* library_path,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000632 uintptr_t start,
633 uintptr_t end) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000634 if (!log_->IsEnabled() || !FLAG_prof) return;
635 LogMessageBuilder msg(this);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000636 msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
637 library_path,
638 start,
639 end);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000640 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000641}
642
643
644void Logger::SharedLibraryEvent(const wchar_t* library_path,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000645 uintptr_t start,
646 uintptr_t end) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000647 if (!log_->IsEnabled() || !FLAG_prof) return;
648 LogMessageBuilder msg(this);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000649 msg.Append("shared-library,\"%ls\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
650 library_path,
651 start,
652 end);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000653 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000654}
655
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000656
ager@chromium.org236ad962008-09-25 09:45:57 +0000657void Logger::LogRegExpSource(Handle<JSRegExp> regexp) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000658 // Prints "/" + re.source + "/" +
659 // (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000660 LogMessageBuilder msg(this);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000661
662 Handle<Object> source = GetProperty(regexp, "source");
663 if (!source->IsString()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000664 msg.Append("no source");
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000665 return;
666 }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000667
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000668 switch (regexp->TypeTag()) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000669 case JSRegExp::ATOM:
ager@chromium.org381abbb2009-02-25 13:23:22 +0000670 msg.Append('a');
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000671 break;
672 default:
673 break;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000674 }
ager@chromium.org381abbb2009-02-25 13:23:22 +0000675 msg.Append('/');
676 msg.AppendDetailed(*Handle<String>::cast(source), false);
677 msg.Append('/');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000678
679 // global flag
680 Handle<Object> global = GetProperty(regexp, "global");
681 if (global->IsTrue()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000682 msg.Append('g');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000683 }
684 // ignorecase flag
685 Handle<Object> ignorecase = GetProperty(regexp, "ignoreCase");
686 if (ignorecase->IsTrue()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000687 msg.Append('i');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000688 }
689 // multiline flag
690 Handle<Object> multiline = GetProperty(regexp, "multiline");
691 if (multiline->IsTrue()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000692 msg.Append('m');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000693 }
ager@chromium.org381abbb2009-02-25 13:23:22 +0000694
695 msg.WriteToLogFile();
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000696}
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000697
698
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000699void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000700 if (!log_->IsEnabled() || !FLAG_log_regexp) return;
701 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000702 msg.Append("regexp-compile,");
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000703 LogRegExpSource(regexp);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000704 msg.Append(in_cache ? ",hit\n" : ",miss\n");
705 msg.WriteToLogFile();
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000706}
707
708
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000709void Logger::LogRuntime(Vector<const char> format, JSArray* args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000710 if (!log_->IsEnabled() || !FLAG_log_runtime) return;
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000711 HandleScope scope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000712 LogMessageBuilder msg(this);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000713 for (int i = 0; i < format.length(); i++) {
714 char c = format[i];
715 if (c == '%' && i <= format.length() - 2) {
716 i++;
717 ASSERT('0' <= format[i] && format[i] <= '9');
lrn@chromium.org303ada72010-10-27 09:33:13 +0000718 MaybeObject* maybe = args->GetElement(format[i] - '0');
719 Object* obj;
720 if (!maybe->ToObject(&obj)) {
721 msg.Append("<exception>");
722 continue;
723 }
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000724 i++;
725 switch (format[i]) {
726 case 's':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000727 msg.AppendDetailed(String::cast(obj), false);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000728 break;
729 case 'S':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000730 msg.AppendDetailed(String::cast(obj), true);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000731 break;
732 case 'r':
733 Logger::LogRegExpSource(Handle<JSRegExp>(JSRegExp::cast(obj)));
734 break;
735 case 'x':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000736 msg.Append("0x%x", Smi::cast(obj)->value());
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000737 break;
738 case 'i':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000739 msg.Append("%i", Smi::cast(obj)->value());
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000740 break;
741 default:
742 UNREACHABLE();
743 }
744 } else {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000745 msg.Append(c);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000746 }
747 }
ager@chromium.org381abbb2009-02-25 13:23:22 +0000748 msg.Append('\n');
749 msg.WriteToLogFile();
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000750}
751
752
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000753void Logger::ApiIndexedSecurityCheck(uint32_t index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000754 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000755 ApiEvent("api,check-security,%u\n", index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000756}
757
758
759void Logger::ApiNamedPropertyAccess(const char* tag,
760 JSObject* holder,
761 Object* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762 ASSERT(name->IsString());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000763 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000764 String* class_name_obj = holder->class_name();
765 SmartPointer<char> class_name =
766 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
767 SmartPointer<char> property_name =
768 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000769 ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000770}
771
772void Logger::ApiIndexedPropertyAccess(const char* tag,
773 JSObject* holder,
774 uint32_t index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000775 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000776 String* class_name_obj = holder->class_name();
777 SmartPointer<char> class_name =
778 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000779 ApiEvent("api,%s,\"%s\",%u\n", tag, *class_name, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000780}
781
782void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000783 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000784 String* class_name_obj = object->class_name();
785 SmartPointer<char> class_name =
786 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000787 ApiEvent("api,%s,\"%s\"\n", tag, *class_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000788}
789
790
791void Logger::ApiEntryCall(const char* name) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000792 if (!log_->IsEnabled() || !FLAG_log_api) return;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000793 ApiEvent("api,%s\n", name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000794}
795
796
797void Logger::NewEvent(const char* name, void* object, size_t size) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000798 if (!log_->IsEnabled() || !FLAG_log) return;
799 LogMessageBuilder msg(this);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000800 msg.Append("new,%s,0x%" V8PRIxPTR ",%u\n", name, object,
ager@chromium.org381abbb2009-02-25 13:23:22 +0000801 static_cast<unsigned int>(size));
802 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000803}
804
805
806void Logger::DeleteEvent(const char* name, void* object) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000807 if (!log_->IsEnabled() || !FLAG_log) return;
808 LogMessageBuilder msg(this);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000809 msg.Append("delete,%s,0x%" V8PRIxPTR "\n", name, object);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000810 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000811}
812
813
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000814void Logger::NewEventStatic(const char* name, void* object, size_t size) {
815 LOGGER->NewEvent(name, object, size);
816}
817
818
819void Logger::DeleteEventStatic(const char* name, void* object) {
820 LOGGER->DeleteEvent(name, object);
821}
822
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000823void Logger::CallbackEventInternal(const char* prefix, const char* name,
824 Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000825 if (!log_->IsEnabled() || !FLAG_log_code) return;
826 LogMessageBuilder msg(this);
ager@chromium.org01beca72009-11-24 14:29:16 +0000827 msg.Append("%s,%s,",
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000828 kLogEventsNames[CODE_CREATION_EVENT],
829 kLogEventsNames[CALLBACK_TAG]);
ager@chromium.org01beca72009-11-24 14:29:16 +0000830 msg.AppendAddress(entry_point);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000831 msg.Append(",1,\"%s%s\"", prefix, name);
ager@chromium.org01beca72009-11-24 14:29:16 +0000832 msg.Append('\n');
833 msg.WriteToLogFile();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000834}
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000835
836
837void Logger::CallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000838 if (!log_->IsEnabled() || !FLAG_log_code) return;
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000839 SmartPointer<char> str =
840 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
841 CallbackEventInternal("", *str, entry_point);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000842}
843
844
845void Logger::GetterCallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000846 if (!log_->IsEnabled() || !FLAG_log_code) return;
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000847 SmartPointer<char> str =
848 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
849 CallbackEventInternal("get ", *str, entry_point);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000850}
851
852
853void Logger::SetterCallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000854 if (!log_->IsEnabled() || !FLAG_log_code) return;
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000855 SmartPointer<char> str =
856 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
857 CallbackEventInternal("set ", *str, entry_point);
ager@chromium.org01beca72009-11-24 14:29:16 +0000858}
859
860
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000861void Logger::CodeCreateEvent(LogEventsAndTags tag,
862 Code* code,
863 const char* comment) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000864 if (!log_->IsEnabled()) return;
865 if (FLAG_ll_prof || Serializer::enabled()) {
866 name_buffer_->Reset();
867 name_buffer_->AppendBytes(kLogEventsNames[tag]);
868 name_buffer_->AppendByte(':');
869 name_buffer_->AppendBytes(comment);
870 }
871 if (FLAG_ll_prof) {
872 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
873 }
874 if (Serializer::enabled()) {
875 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
876 }
877 if (!FLAG_log_code) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000878 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000879 msg.Append("%s,%s,",
880 kLogEventsNames[CODE_CREATION_EVENT],
881 kLogEventsNames[tag]);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000882 msg.AppendAddress(code->address());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000883 msg.Append(",%d,\"", code->ExecutableSize());
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000884 for (const char* p = comment; *p != '\0'; p++) {
885 if (*p == '"') {
886 msg.Append('\\');
887 }
888 msg.Append(*p);
889 }
890 msg.Append('"');
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000891 msg.Append('\n');
892 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000893}
894
895
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000896void Logger::CodeCreateEvent(LogEventsAndTags tag,
897 Code* code,
898 String* name) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000899 if (!log_->IsEnabled()) return;
900 if (FLAG_ll_prof || Serializer::enabled()) {
901 name_buffer_->Reset();
902 name_buffer_->AppendBytes(kLogEventsNames[tag]);
903 name_buffer_->AppendByte(':');
904 name_buffer_->AppendString(name);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000905 }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000906 if (FLAG_ll_prof) {
907 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
908 }
909 if (Serializer::enabled()) {
910 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
911 }
912 if (!FLAG_log_code) return;
913 LogMessageBuilder msg(this);
914 msg.Append("%s,%s,",
915 kLogEventsNames[CODE_CREATION_EVENT],
916 kLogEventsNames[tag]);
917 msg.AppendAddress(code->address());
918 msg.Append(",%d,\"", code->ExecutableSize());
919 msg.AppendDetailed(name, false);
920 msg.Append('"');
921 msg.Append('\n');
922 msg.WriteToLogFile();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000923}
924
925
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000926// ComputeMarker must only be used when SharedFunctionInfo is known.
927static const char* ComputeMarker(Code* code) {
928 switch (code->kind()) {
929 case Code::FUNCTION: return code->optimizable() ? "~" : "";
930 case Code::OPTIMIZED_FUNCTION: return "*";
931 default: return "";
932 }
933}
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000934
935
936void Logger::CodeCreateEvent(LogEventsAndTags tag,
937 Code* code,
938 SharedFunctionInfo* shared,
939 String* name) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000940 if (!log_->IsEnabled()) return;
941 if (FLAG_ll_prof || Serializer::enabled()) {
942 name_buffer_->Reset();
943 name_buffer_->AppendBytes(kLogEventsNames[tag]);
944 name_buffer_->AppendByte(':');
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000945 name_buffer_->AppendBytes(ComputeMarker(code));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000946 name_buffer_->AppendString(name);
947 }
948 if (FLAG_ll_prof) {
949 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
950 }
951 if (Serializer::enabled()) {
952 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
953 }
954 if (!FLAG_log_code) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000955 if (code == Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000956 Builtins::kLazyCompile))
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000957 return;
958
959 LogMessageBuilder msg(this);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000960 SmartPointer<char> str =
961 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000962 msg.Append("%s,%s,",
963 kLogEventsNames[CODE_CREATION_EVENT],
964 kLogEventsNames[tag]);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000965 msg.AppendAddress(code->address());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000966 msg.Append(",%d,\"%s\",", code->ExecutableSize(), *str);
967 msg.AppendAddress(shared->address());
968 msg.Append(",%s", ComputeMarker(code));
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000969 msg.Append('\n');
970 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000971}
972
973
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000974// Although, it is possible to extract source and line from
975// the SharedFunctionInfo object, we left it to caller
976// to leave logging functions free from heap allocations.
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000977void Logger::CodeCreateEvent(LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000978 Code* code,
979 SharedFunctionInfo* shared,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000980 String* source, int line) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000981 if (!log_->IsEnabled()) return;
982 if (FLAG_ll_prof || Serializer::enabled()) {
983 name_buffer_->Reset();
984 name_buffer_->AppendBytes(kLogEventsNames[tag]);
985 name_buffer_->AppendByte(':');
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000986 name_buffer_->AppendBytes(ComputeMarker(code));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000987 name_buffer_->AppendString(shared->DebugName());
988 name_buffer_->AppendByte(' ');
989 name_buffer_->AppendString(source);
990 name_buffer_->AppendByte(':');
991 name_buffer_->AppendInt(line);
992 }
993 if (FLAG_ll_prof) {
994 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
995 }
996 if (Serializer::enabled()) {
997 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
998 }
999 if (!FLAG_log_code) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001000 LogMessageBuilder msg(this);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001001 SmartPointer<char> name =
1002 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001003 SmartPointer<char> sourcestr =
1004 source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001005 msg.Append("%s,%s,",
1006 kLogEventsNames[CODE_CREATION_EVENT],
1007 kLogEventsNames[tag]);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001008 msg.AppendAddress(code->address());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001009 msg.Append(",%d,\"%s %s:%d\",",
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001010 code->ExecutableSize(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001011 *name,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001012 *sourcestr,
1013 line);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001014 msg.AppendAddress(shared->address());
1015 msg.Append(",%s", ComputeMarker(code));
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001016 msg.Append('\n');
1017 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001018}
1019
1020
1021void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001022 if (!log_->IsEnabled()) return;
1023 if (FLAG_ll_prof || Serializer::enabled()) {
1024 name_buffer_->Reset();
1025 name_buffer_->AppendBytes(kLogEventsNames[tag]);
1026 name_buffer_->AppendByte(':');
1027 name_buffer_->AppendInt(args_count);
1028 }
1029 if (FLAG_ll_prof) {
1030 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
1031 }
1032 if (Serializer::enabled()) {
1033 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
1034 }
1035 if (!FLAG_log_code) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001036 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001037 msg.Append("%s,%s,",
1038 kLogEventsNames[CODE_CREATION_EVENT],
1039 kLogEventsNames[tag]);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001040 msg.AppendAddress(code->address());
1041 msg.Append(",%d,\"args_count: %d\"", code->ExecutableSize(), args_count);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001042 msg.Append('\n');
1043 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001044}
1045
1046
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001047void Logger::CodeMovingGCEvent() {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001048 if (!log_->IsEnabled() || !FLAG_ll_prof) return;
1049 LowLevelLogWriteBytes(&kCodeMovingGCTag, sizeof(kCodeMovingGCTag));
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001050 OS::SignalCodeMovingGC();
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001051}
1052
1053
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001054void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001055 if (!log_->IsEnabled()) return;
1056 if (FLAG_ll_prof || Serializer::enabled()) {
1057 name_buffer_->Reset();
1058 name_buffer_->AppendBytes(kLogEventsNames[REG_EXP_TAG]);
1059 name_buffer_->AppendByte(':');
1060 name_buffer_->AppendString(source);
1061 }
1062 if (FLAG_ll_prof) {
1063 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
1064 }
1065 if (Serializer::enabled()) {
1066 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
1067 }
1068 if (!FLAG_log_code) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001069 LogMessageBuilder msg(this);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001070 msg.Append("%s,%s,",
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001071 kLogEventsNames[CODE_CREATION_EVENT],
1072 kLogEventsNames[REG_EXP_TAG]);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001073 msg.AppendAddress(code->address());
1074 msg.Append(",%d,\"", code->ExecutableSize());
1075 msg.AppendDetailed(source, false);
1076 msg.Append('\"');
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001077 msg.Append('\n');
1078 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001079}
1080
1081
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001082void Logger::CodeMoveEvent(Address from, Address to) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001083 if (!log_->IsEnabled()) return;
1084 if (FLAG_ll_prof) LowLevelCodeMoveEvent(from, to);
1085 if (Serializer::enabled() && address_to_name_map_ != NULL) {
1086 address_to_name_map_->Move(from, to);
1087 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001088 MoveEventInternal(CODE_MOVE_EVENT, from, to);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001089}
1090
1091
1092void Logger::CodeDeleteEvent(Address from) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001093 if (!log_->IsEnabled()) return;
1094 if (FLAG_ll_prof) LowLevelCodeDeleteEvent(from);
1095 if (Serializer::enabled() && address_to_name_map_ != NULL) {
1096 address_to_name_map_->Remove(from);
1097 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001098 DeleteEventInternal(CODE_DELETE_EVENT, from);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001099}
1100
1101
1102void Logger::SnapshotPositionEvent(Address addr, int pos) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001103 if (!log_->IsEnabled()) return;
1104 if (FLAG_ll_prof) LowLevelSnapshotPositionEvent(addr, pos);
1105 if (Serializer::enabled() && address_to_name_map_ != NULL) {
1106 const char* code_name = address_to_name_map_->Lookup(addr);
1107 if (code_name == NULL) return; // Not a code object.
1108 LogMessageBuilder msg(this);
1109 msg.Append("%s,%d,\"", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
1110 for (const char* p = code_name; *p != '\0'; ++p) {
1111 if (*p == '"') msg.Append('\\');
1112 msg.Append(*p);
1113 }
1114 msg.Append("\"\n");
1115 msg.WriteToLogFile();
1116 }
1117 if (!FLAG_log_snapshot_positions) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001118 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001119 msg.Append("%s,", kLogEventsNames[SNAPSHOT_POSITION_EVENT]);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001120 msg.AppendAddress(addr);
1121 msg.Append(",%d", pos);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001122 msg.Append('\n');
1123 msg.WriteToLogFile();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001124}
1125
1126
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001127void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001128 MoveEventInternal(SHARED_FUNC_MOVE_EVENT, from, to);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001129}
1130
1131
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001132void Logger::MoveEventInternal(LogEventsAndTags event,
1133 Address from,
1134 Address to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001135 if (!log_->IsEnabled() || !FLAG_log_code) return;
1136 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001137 msg.Append("%s,", kLogEventsNames[event]);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001138 msg.AppendAddress(from);
1139 msg.Append(',');
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001140 msg.AppendAddress(to);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001141 msg.Append('\n');
ager@chromium.org381abbb2009-02-25 13:23:22 +00001142 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001143}
1144
1145
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001146void Logger::DeleteEventInternal(LogEventsAndTags event, Address from) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001147 if (!log_->IsEnabled() || !FLAG_log_code) return;
1148 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001149 msg.Append("%s,", kLogEventsNames[event]);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001150 msg.AppendAddress(from);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001151 msg.Append('\n');
ager@chromium.org381abbb2009-02-25 13:23:22 +00001152 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001153}
1154
1155
1156void Logger::ResourceEvent(const char* name, const char* tag) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001157 if (!log_->IsEnabled() || !FLAG_log) return;
1158 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001159 msg.Append("%s,%s,", name, tag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001160
1161 uint32_t sec, usec;
1162 if (OS::GetUserTime(&sec, &usec) != -1) {
ager@chromium.org381abbb2009-02-25 13:23:22 +00001163 msg.Append("%d,%d,", sec, usec);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001164 }
ager@chromium.org381abbb2009-02-25 13:23:22 +00001165 msg.Append("%.0f", OS::TimeCurrentMillis());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001166
ager@chromium.org381abbb2009-02-25 13:23:22 +00001167 msg.Append('\n');
1168 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001169}
1170
1171
ager@chromium.org8bb60582008-12-11 12:02:20 +00001172void Logger::SuspectReadEvent(String* name, Object* obj) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001173 if (!log_->IsEnabled() || !FLAG_log_suspect) return;
1174 LogMessageBuilder msg(this);
ager@chromium.org8bb60582008-12-11 12:02:20 +00001175 String* class_name = obj->IsJSObject()
1176 ? JSObject::cast(obj)->class_name()
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001177 : HEAP->empty_string();
ager@chromium.org381abbb2009-02-25 13:23:22 +00001178 msg.Append("suspect-read,");
1179 msg.Append(class_name);
1180 msg.Append(',');
1181 msg.Append('"');
1182 msg.Append(name);
1183 msg.Append('"');
1184 msg.Append('\n');
1185 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001186}
1187
1188
1189void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001190 if (!log_->IsEnabled() || !FLAG_log_gc) return;
1191 LogMessageBuilder msg(this);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001192 // Using non-relative system time in order to be able to synchronize with
1193 // external memory profiling events (e.g. DOM memory size).
1194 msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f\n",
1195 space, kind, OS::TimeCurrentMillis());
1196 msg.WriteToLogFile();
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001197}
1198
1199
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001200void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001201 if (!log_->IsEnabled() || !FLAG_log_gc) return;
1202 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001203 msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind);
1204 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001205}
1206
1207
1208void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001209 if (!log_->IsEnabled() || !FLAG_log_gc) return;
1210 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001211 msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes);
1212 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001213}
1214
1215
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001216void Logger::DebugTag(const char* call_site_tag) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001217 if (!log_->IsEnabled() || !FLAG_log) return;
1218 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001219 msg.Append("debug-tag,%s\n", call_site_tag);
1220 msg.WriteToLogFile();
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001221}
1222
1223
1224void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001225 if (!log_->IsEnabled() || !FLAG_log) return;
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001226 StringBuilder s(parameter.length() + 1);
1227 for (int i = 0; i < parameter.length(); ++i) {
1228 s.AddCharacter(static_cast<char>(parameter[i]));
1229 }
1230 char* parameter_string = s.Finalize();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001231 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001232 msg.Append("debug-queue-event,%s,%15.3f,%s\n",
1233 event_type,
1234 OS::TimeCurrentMillis(),
1235 parameter_string);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001236 DeleteArray(parameter_string);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001237 msg.WriteToLogFile();
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001238}
1239
1240
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001241void Logger::TickEvent(TickSample* sample, bool overflow) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001242 if (!log_->IsEnabled() || !FLAG_prof) return;
1243 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001244 msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
1245 msg.AppendAddress(sample->pc);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001246 msg.Append(',');
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001247 msg.AppendAddress(sample->sp);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001248 if (sample->has_external_callback) {
1249 msg.Append(",1,");
1250 msg.AppendAddress(sample->external_callback);
1251 } else {
1252 msg.Append(",0,");
1253 msg.AppendAddress(sample->tos);
1254 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001255 msg.Append(",%d", static_cast<int>(sample->state));
ager@chromium.org381abbb2009-02-25 13:23:22 +00001256 if (overflow) {
1257 msg.Append(",overflow");
1258 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001259 for (int i = 0; i < sample->frames_count; ++i) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001260 msg.Append(',');
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001261 msg.AppendAddress(sample->stack[i]);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001262 }
1263 msg.Append('\n');
1264 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001265}
iposva@chromium.org245aa852009-02-10 00:49:54 +00001266
1267
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001268bool Logger::IsProfilerPaused() {
1269 return profiler_ == NULL || profiler_->paused();
iposva@chromium.org245aa852009-02-10 00:49:54 +00001270}
1271
1272
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001273void Logger::PauseProfiler() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001274 if (!log_->IsEnabled()) return;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001275 if (profiler_ != NULL) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001276 // It is OK to have negative nesting.
1277 if (--cpu_profiler_nesting_ == 0) {
1278 profiler_->pause();
1279 if (FLAG_prof_lazy) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001280 if (!FLAG_sliding_state_window && !RuntimeProfiler::IsEnabled()) {
1281 ticker_->Stop();
1282 }
ager@chromium.org5c838252010-02-19 08:53:10 +00001283 FLAG_log_code = false;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001284 LOG(ISOLATE, UncheckedStringEvent("profiler", "pause"));
ager@chromium.org5c838252010-02-19 08:53:10 +00001285 }
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001286 --logging_nesting_;
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00001287 }
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001288 }
iposva@chromium.org245aa852009-02-10 00:49:54 +00001289}
1290
1291
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001292void Logger::ResumeProfiler() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001293 if (!log_->IsEnabled()) return;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001294 if (profiler_ != NULL) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001295 if (cpu_profiler_nesting_++ == 0) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001296 ++logging_nesting_;
ager@chromium.org5c838252010-02-19 08:53:10 +00001297 if (FLAG_prof_lazy) {
1298 profiler_->Engage();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001299 LOG(ISOLATE, UncheckedStringEvent("profiler", "resume"));
ager@chromium.org5c838252010-02-19 08:53:10 +00001300 FLAG_log_code = true;
1301 LogCompiledFunctions();
ager@chromium.org5c838252010-02-19 08:53:10 +00001302 LogAccessorCallbacks();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001303 if (!FLAG_sliding_state_window && !ticker_->IsActive()) {
1304 ticker_->Start();
1305 }
ager@chromium.org5c838252010-02-19 08:53:10 +00001306 }
1307 profiler_->resume();
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00001308 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001309 }
iposva@chromium.org245aa852009-02-10 00:49:54 +00001310}
ager@chromium.org9085a012009-05-11 19:22:57 +00001311
1312
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001313// This function can be called when Log's mutex is acquired,
1314// either from main or Profiler's thread.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001315void Logger::LogFailure() {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001316 PauseProfiler();
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001317}
1318
1319
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001320bool Logger::IsProfilerSamplerActive() {
1321 return ticker_->IsActive();
1322}
1323
1324
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001325class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor {
1326 public:
1327 EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis,
1328 Handle<Code>* code_objects,
1329 int* count)
1330 : sfis_(sfis), code_objects_(code_objects), count_(count) { }
1331
1332 virtual void EnterContext(Context* context) {}
1333 virtual void LeaveContext(Context* context) {}
1334
1335 virtual void VisitFunction(JSFunction* function) {
whesse@chromium.org7b260152011-06-20 15:33:18 +00001336 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(function->shared());
1337 Object* maybe_script = sfi->script();
1338 if (maybe_script->IsScript()
1339 && !Script::cast(maybe_script)->HasValidSource()) return;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001340 if (sfis_ != NULL) {
whesse@chromium.org7b260152011-06-20 15:33:18 +00001341 sfis_[*count_] = Handle<SharedFunctionInfo>(sfi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001342 }
1343 if (code_objects_ != NULL) {
1344 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
1345 code_objects_[*count_] = Handle<Code>(function->code());
1346 }
1347 *count_ = *count_ + 1;
1348 }
1349
1350 private:
1351 Handle<SharedFunctionInfo>* sfis_;
1352 Handle<Code>* code_objects_;
1353 int* count_;
1354};
1355
1356
1357static int EnumerateCompiledFunctions(Handle<SharedFunctionInfo>* sfis,
1358 Handle<Code>* code_objects) {
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001359 AssertNoAllocation no_alloc;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001360 int compiled_funcs_count = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001361
1362 // Iterate the heap to find shared function info objects and record
1363 // the unoptimized code for them.
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001364 HeapIterator iterator;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001365 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001366 if (!obj->IsSharedFunctionInfo()) continue;
1367 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
1368 if (sfi->is_compiled()
1369 && (!sfi->script()->IsScript()
1370 || Script::cast(sfi->script())->HasValidSource())) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001371 if (sfis != NULL) {
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001372 sfis[compiled_funcs_count] = Handle<SharedFunctionInfo>(sfi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001373 }
1374 if (code_objects != NULL) {
1375 code_objects[compiled_funcs_count] = Handle<Code>(sfi->code());
1376 }
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001377 ++compiled_funcs_count;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001378 }
1379 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001380
1381 // Iterate all optimized functions in all contexts.
1382 EnumerateOptimizedFunctionsVisitor visitor(sfis,
1383 code_objects,
1384 &compiled_funcs_count);
1385 Deoptimizer::VisitAllOptimizedFunctions(&visitor);
1386
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001387 return compiled_funcs_count;
1388}
1389
1390
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001391void Logger::LogCodeObject(Object* object) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001392 if (FLAG_log_code || FLAG_ll_prof) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001393 Code* code_object = Code::cast(object);
1394 LogEventsAndTags tag = Logger::STUB_TAG;
1395 const char* description = "Unknown code from the snapshot";
1396 switch (code_object->kind()) {
1397 case Code::FUNCTION:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001398 case Code::OPTIMIZED_FUNCTION:
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001399 return; // We log this later using LogCompiledFunctions.
danno@chromium.org40cb8782011-05-25 07:58:50 +00001400 case Code::UNARY_OP_IC: // fall through
1401 case Code::BINARY_OP_IC: // fall through
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001402 case Code::COMPARE_IC: // fall through
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001403 case Code::TO_BOOLEAN_IC: // fall through
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001404 case Code::STUB:
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001405 description =
1406 CodeStub::MajorName(CodeStub::GetMajorKey(code_object), true);
ager@chromium.org5c838252010-02-19 08:53:10 +00001407 if (description == NULL)
1408 description = "A stub from the snapshot";
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001409 tag = Logger::STUB_TAG;
1410 break;
1411 case Code::BUILTIN:
1412 description = "A builtin from the snapshot";
1413 tag = Logger::BUILTIN_TAG;
1414 break;
1415 case Code::KEYED_LOAD_IC:
1416 description = "A keyed load IC from the snapshot";
1417 tag = Logger::KEYED_LOAD_IC_TAG;
1418 break;
1419 case Code::LOAD_IC:
1420 description = "A load IC from the snapshot";
1421 tag = Logger::LOAD_IC_TAG;
1422 break;
1423 case Code::STORE_IC:
1424 description = "A store IC from the snapshot";
1425 tag = Logger::STORE_IC_TAG;
1426 break;
1427 case Code::KEYED_STORE_IC:
1428 description = "A keyed store IC from the snapshot";
1429 tag = Logger::KEYED_STORE_IC_TAG;
1430 break;
1431 case Code::CALL_IC:
1432 description = "A call IC from the snapshot";
1433 tag = Logger::CALL_IC_TAG;
1434 break;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001435 case Code::KEYED_CALL_IC:
1436 description = "A keyed call IC from the snapshot";
1437 tag = Logger::KEYED_CALL_IC_TAG;
1438 break;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001439 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001440 PROFILE(ISOLATE, CodeCreateEvent(tag, code_object, description));
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001441 }
1442}
1443
1444
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001445void Logger::LogCodeInfo() {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001446 if (!log_->IsEnabled() || !FLAG_ll_prof) return;
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001447#if V8_TARGET_ARCH_IA32
1448 const char arch[] = "ia32";
1449#elif V8_TARGET_ARCH_X64
1450 const char arch[] = "x64";
1451#elif V8_TARGET_ARCH_ARM
1452 const char arch[] = "arm";
1453#else
1454 const char arch[] = "unknown";
1455#endif
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001456 LowLevelLogWriteBytes(arch, sizeof(arch));
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001457}
1458
1459
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001460void Logger::RegisterSnapshotCodeName(Code* code,
1461 const char* name,
1462 int name_size) {
1463 ASSERT(Serializer::enabled());
1464 if (address_to_name_map_ == NULL) {
1465 address_to_name_map_ = new NameMap;
1466 }
1467 address_to_name_map_->Insert(code->address(), name, name_size);
1468}
1469
1470
1471void Logger::LowLevelCodeCreateEvent(Code* code,
1472 const char* name,
1473 int name_size) {
1474 if (log_->ll_output_handle_ == NULL) return;
1475 LowLevelCodeCreateStruct event;
1476 event.name_size = name_size;
1477 event.code_address = code->instruction_start();
1478 ASSERT(event.code_address == code->address() + Code::kHeaderSize);
1479 event.code_size = code->instruction_size();
1480 LowLevelLogWriteStruct(event);
1481 LowLevelLogWriteBytes(name, name_size);
1482 LowLevelLogWriteBytes(
1483 reinterpret_cast<const char*>(code->instruction_start()),
1484 code->instruction_size());
1485}
1486
1487
1488void Logger::LowLevelCodeMoveEvent(Address from, Address to) {
1489 if (log_->ll_output_handle_ == NULL) return;
1490 LowLevelCodeMoveStruct event;
1491 event.from_address = from + Code::kHeaderSize;
1492 event.to_address = to + Code::kHeaderSize;
1493 LowLevelLogWriteStruct(event);
1494}
1495
1496
1497void Logger::LowLevelCodeDeleteEvent(Address from) {
1498 if (log_->ll_output_handle_ == NULL) return;
1499 LowLevelCodeDeleteStruct event;
1500 event.address = from + Code::kHeaderSize;
1501 LowLevelLogWriteStruct(event);
1502}
1503
1504
1505void Logger::LowLevelSnapshotPositionEvent(Address addr, int pos) {
1506 if (log_->ll_output_handle_ == NULL) return;
1507 LowLevelSnapshotPositionStruct event;
1508 event.address = addr + Code::kHeaderSize;
1509 event.position = pos;
1510 LowLevelLogWriteStruct(event);
1511}
1512
1513
1514void Logger::LowLevelLogWriteBytes(const char* bytes, int size) {
1515 size_t rv = fwrite(bytes, 1, size, log_->ll_output_handle_);
1516 ASSERT(static_cast<size_t>(size) == rv);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001517 USE(rv);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001518}
1519
1520
ager@chromium.org5c838252010-02-19 08:53:10 +00001521void Logger::LogCodeObjects() {
1522 AssertNoAllocation no_alloc;
1523 HeapIterator iterator;
1524 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1525 if (obj->IsCode()) LogCodeObject(obj);
1526 }
1527}
1528
1529
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001530void Logger::LogCompiledFunctions() {
1531 HandleScope scope;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001532 const int compiled_funcs_count = EnumerateCompiledFunctions(NULL, NULL);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001533 ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001534 ScopedVector< Handle<Code> > code_objects(compiled_funcs_count);
1535 EnumerateCompiledFunctions(sfis.start(), code_objects.start());
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001536
1537 // During iteration, there can be heap allocation due to
1538 // GetScriptLineNumber call.
1539 for (int i = 0; i < compiled_funcs_count; ++i) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001540 if (*code_objects[i] == Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001541 Builtins::kLazyCompile))
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001542 continue;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001543 Handle<SharedFunctionInfo> shared = sfis[i];
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001544 Handle<String> func_name(shared->DebugName());
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001545 if (shared->script()->IsScript()) {
1546 Handle<Script> script(Script::cast(shared->script()));
1547 if (script->name()->IsString()) {
1548 Handle<String> script_name(String::cast(script->name()));
1549 int line_num = GetScriptLineNumber(script, shared->start_position());
1550 if (line_num > 0) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001551 PROFILE(ISOLATE,
1552 CodeCreateEvent(
1553 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
1554 *code_objects[i], *shared,
1555 *script_name, line_num + 1));
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001556 } else {
ager@chromium.org357bf652010-04-12 11:30:10 +00001557 // Can't distinguish eval and script here, so always use Script.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001558 PROFILE(ISOLATE,
1559 CodeCreateEvent(
1560 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
1561 *code_objects[i], *shared, *script_name));
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001562 }
ager@chromium.org01beca72009-11-24 14:29:16 +00001563 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001564 PROFILE(ISOLATE,
1565 CodeCreateEvent(
1566 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
1567 *code_objects[i], *shared, *func_name));
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001568 }
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00001569 } else if (shared->IsApiFunction()) {
ager@chromium.org01beca72009-11-24 14:29:16 +00001570 // API function.
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00001571 FunctionTemplateInfo* fun_data = shared->get_api_func_data();
ager@chromium.org01beca72009-11-24 14:29:16 +00001572 Object* raw_call_data = fun_data->call_code();
1573 if (!raw_call_data->IsUndefined()) {
1574 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1575 Object* callback_obj = call_data->callback();
1576 Address entry_point = v8::ToCData<Address>(callback_obj);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001577 PROFILE(ISOLATE, CallbackEvent(*func_name, entry_point));
ager@chromium.org01beca72009-11-24 14:29:16 +00001578 }
1579 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001580 PROFILE(ISOLATE,
1581 CodeCreateEvent(
1582 Logger::LAZY_COMPILE_TAG, *code_objects[i],
1583 *shared, *func_name));
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001584 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001585 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001586}
1587
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001588
1589void Logger::LogAccessorCallbacks() {
1590 AssertNoAllocation no_alloc;
1591 HeapIterator iterator;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001592 i::Isolate* isolate = ISOLATE;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001593 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001594 if (!obj->IsAccessorInfo()) continue;
1595 AccessorInfo* ai = AccessorInfo::cast(obj);
1596 if (!ai->name()->IsString()) continue;
1597 String* name = String::cast(ai->name());
1598 Address getter_entry = v8::ToCData<Address>(ai->getter());
1599 if (getter_entry != 0) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001600 PROFILE(isolate, GetterCallbackEvent(name, getter_entry));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001601 }
1602 Address setter_entry = v8::ToCData<Address>(ai->setter());
1603 if (setter_entry != 0) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001604 PROFILE(isolate, SetterCallbackEvent(name, setter_entry));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001605 }
1606 }
1607}
1608
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001609
1610bool Logger::Setup() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001611 // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
1612 if (is_initialized_) return true;
1613 is_initialized_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001614
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001615 // --ll-prof implies --log-code and --log-snapshot-positions.
1616 if (FLAG_ll_prof) {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001617 FLAG_log_snapshot_positions = true;
1618 }
1619
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001620 // --prof_lazy controls --log-code, implies --noprof_auto.
1621 if (FLAG_prof_lazy) {
1622 FLAG_log_code = false;
1623 FLAG_prof_auto = false;
1624 }
1625
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001626 // TODO(isolates): this assert introduces cyclic dependency (logger
1627 // -> thread local top -> heap -> logger).
1628 // ASSERT(VMState::is_outermost_external());
ager@chromium.org3e875802009-06-29 08:26:34 +00001629
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001630 log_->Initialize();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001631
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001632 if (FLAG_ll_prof) LogCodeInfo();
1633
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001634 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001635 ticker_ = new Ticker(isolate, kSamplingIntervalMs);
1636
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001637 if (FLAG_sliding_state_window && sliding_state_window_ == NULL) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001638 sliding_state_window_ = new SlidingStateWindow(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001639 }
1640
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001641 bool start_logging = FLAG_log || FLAG_log_runtime || FLAG_log_api
1642 || FLAG_log_code || FLAG_log_gc || FLAG_log_handles || FLAG_log_suspect
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001643 || FLAG_log_regexp || FLAG_log_state_changes || FLAG_ll_prof;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001644
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001645 if (start_logging) {
1646 logging_nesting_ = 1;
1647 }
ager@chromium.org3e875802009-06-29 08:26:34 +00001648
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001649 if (FLAG_prof) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001650 profiler_ = new Profiler(isolate);
ager@chromium.org3e875802009-06-29 08:26:34 +00001651 if (!FLAG_prof_auto) {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001652 profiler_->pause();
ager@chromium.org3e875802009-06-29 08:26:34 +00001653 } else {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001654 logging_nesting_ = 1;
ager@chromium.org3e875802009-06-29 08:26:34 +00001655 }
ager@chromium.org3811b432009-10-28 14:53:37 +00001656 if (!FLAG_prof_lazy) {
1657 profiler_->Engage();
1658 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001659 }
1660
1661 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001662}
1663
1664
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001665Sampler* Logger::sampler() {
1666 return ticker_;
1667}
1668
1669
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001670void Logger::EnsureTickerStarted() {
1671 ASSERT(ticker_ != NULL);
1672 if (!ticker_->IsActive()) ticker_->Start();
1673}
1674
1675
1676void Logger::EnsureTickerStopped() {
1677 if (ticker_ != NULL && ticker_->IsActive()) ticker_->Stop();
1678}
1679
1680
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001681FILE* Logger::TearDown() {
1682 if (!is_initialized_) return NULL;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001683 is_initialized_ = false;
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001684
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001685 // Stop the profiler before closing the file.
1686 if (profiler_ != NULL) {
1687 profiler_->Disengage();
1688 delete profiler_;
1689 profiler_ = NULL;
1690 }
1691
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001692 delete sliding_state_window_;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001693 sliding_state_window_ = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001694
1695 delete ticker_;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001696 ticker_ = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001697
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001698 return log_->Close();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001699}
1700
1701
1702void Logger::EnableSlidingStateWindow() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001703 // If the ticker is NULL, Logger::Setup has not been called yet. In
1704 // that case, we set the sliding_state_window flag so that the
1705 // sliding window computation will be started when Logger::Setup is
1706 // called.
1707 if (ticker_ == NULL) {
1708 FLAG_sliding_state_window = true;
1709 return;
1710 }
1711 // Otherwise, if the sliding state window computation has not been
1712 // started we do it now.
1713 if (sliding_state_window_ == NULL) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001714 sliding_state_window_ = new SlidingStateWindow(Isolate::Current());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001715 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001716}
1717
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001718
1719Mutex* SamplerRegistry::mutex_ = OS::CreateMutex();
1720List<Sampler*>* SamplerRegistry::active_samplers_ = NULL;
1721
1722
1723bool SamplerRegistry::IterateActiveSamplers(VisitSampler func, void* param) {
1724 ScopedLock lock(mutex_);
1725 for (int i = 0;
1726 ActiveSamplersExist() && i < active_samplers_->length();
1727 ++i) {
1728 func(active_samplers_->at(i), param);
1729 }
1730 return ActiveSamplersExist();
1731}
1732
1733
1734static void ComputeCpuProfiling(Sampler* sampler, void* flag_ptr) {
1735 bool* flag = reinterpret_cast<bool*>(flag_ptr);
1736 *flag |= sampler->IsProfiling();
1737}
1738
1739
1740SamplerRegistry::State SamplerRegistry::GetState() {
1741 bool flag = false;
1742 if (!IterateActiveSamplers(&ComputeCpuProfiling, &flag)) {
1743 return HAS_NO_SAMPLERS;
1744 }
1745 return flag ? HAS_CPU_PROFILING_SAMPLERS : HAS_SAMPLERS;
1746}
1747
1748
1749void SamplerRegistry::AddActiveSampler(Sampler* sampler) {
1750 ASSERT(sampler->IsActive());
1751 ScopedLock lock(mutex_);
1752 if (active_samplers_ == NULL) {
1753 active_samplers_ = new List<Sampler*>;
1754 } else {
1755 ASSERT(!active_samplers_->Contains(sampler));
1756 }
1757 active_samplers_->Add(sampler);
1758}
1759
1760
1761void SamplerRegistry::RemoveActiveSampler(Sampler* sampler) {
1762 ASSERT(sampler->IsActive());
1763 ScopedLock lock(mutex_);
1764 ASSERT(active_samplers_ != NULL);
1765 bool removed = active_samplers_->RemoveElement(sampler);
1766 ASSERT(removed);
1767 USE(removed);
1768}
1769
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001770} } // namespace v8::internal