blob: d93a9d82b117022e629f9f84530578e15efed611 [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"
jkummerow@chromium.org1456e702012-03-30 08:38:13 +000038#include "platform.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000039#include "runtime-profiler.h"
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +000040#include "serialize.h"
41#include "string-stream.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000042#include "vm-state-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043
kasperl@chromium.org71affb52009-05-26 05:44:31 +000044namespace v8 {
45namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000047//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000048// Sliding state window. Updates counters to keep track of the last
49// window of kBufferSize states. This is useful to track where we
50// spent our time.
51//
52class SlidingStateWindow {
53 public:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000054 explicit SlidingStateWindow(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000055 ~SlidingStateWindow();
56 void AddState(StateTag state);
57
58 private:
59 static const int kBufferSize = 256;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000060 Counters* counters_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000061 int current_index_;
62 bool is_full_;
63 byte buffer_[kBufferSize];
64
65
66 void IncrementStateCounter(StateTag state) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000067 counters_->state_counters(state)->Increment();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000068 }
69
70
71 void DecrementStateCounter(StateTag state) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000072 counters_->state_counters(state)->Decrement();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000073 }
74};
75
76
77//
78// The Profiler samples pc and sp values for the main thread.
79// Each sample is appended to a circular buffer.
80// An independent thread removes data and writes it to the log.
81// This design minimizes the time spent in the sampler.
82//
83class Profiler: public Thread {
84 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000085 explicit Profiler(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000086 void Engage();
87 void Disengage();
88
89 // Inserts collected profiling data into buffer.
90 void Insert(TickSample* sample) {
iposva@chromium.org245aa852009-02-10 00:49:54 +000091 if (paused_)
92 return;
93
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000094 if (Succ(head_) == tail_) {
95 overflow_ = true;
96 } else {
97 buffer_[head_] = *sample;
98 head_ = Succ(head_);
99 buffer_semaphore_->Signal(); // Tell we have an element.
100 }
101 }
102
103 // Waits for a signal and removes profiling data.
104 bool Remove(TickSample* sample) {
105 buffer_semaphore_->Wait(); // Wait for an element.
106 *sample = buffer_[tail_];
107 bool result = overflow_;
108 tail_ = Succ(tail_);
109 overflow_ = false;
110 return result;
111 }
112
113 void Run();
114
iposva@chromium.org245aa852009-02-10 00:49:54 +0000115 // Pause and Resume TickSample data collection.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000116 bool paused() const { return paused_; }
117 void pause() { paused_ = true; }
118 void resume() { paused_ = false; }
iposva@chromium.org245aa852009-02-10 00:49:54 +0000119
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000120 private:
121 // Returns the next index in the cyclic buffer.
122 int Succ(int index) { return (index + 1) % kBufferSize; }
123
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000124 Isolate* isolate_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000125 // Cyclic buffer for communicating profiling samples
126 // between the signal handler and the worker thread.
127 static const int kBufferSize = 128;
128 TickSample buffer_[kBufferSize]; // Buffer storage.
129 int head_; // Index to the buffer head.
130 int tail_; // Index to the buffer tail.
131 bool overflow_; // Tell whether a buffer overflow has occurred.
132 Semaphore* buffer_semaphore_; // Sempahore used for buffer synchronization.
133
ager@chromium.org3811b432009-10-28 14:53:37 +0000134 // Tells whether profiler is engaged, that is, processing thread is stated.
135 bool engaged_;
136
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000137 // Tells whether worker thread should continue running.
138 bool running_;
iposva@chromium.org245aa852009-02-10 00:49:54 +0000139
140 // Tells whether we are currently recording tick samples.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000141 bool paused_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000142};
143
144
145//
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000146// StackTracer implementation
147//
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000148void StackTracer::Trace(Isolate* isolate, TickSample* sample) {
149 ASSERT(isolate->IsInitialized());
150
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000151 // Avoid collecting traces while doing GC.
lrn@chromium.org25156de2010-04-06 13:10:27 +0000152 if (sample->state == GC) return;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000153
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000154 const Address js_entry_sp =
155 Isolate::js_entry_sp(isolate->thread_local_top());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000156 if (js_entry_sp == 0) {
157 // Not executing JS now.
ager@chromium.orge2902be2009-06-08 12:21:35 +0000158 return;
159 }
160
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000161 const Address callback = isolate->external_callback();
162 if (callback != NULL) {
163 sample->external_callback = callback;
164 sample->has_external_callback = true;
165 } else {
166 // Sample potential return address value for frameless invocation of
167 // stubs (we'll figure out later, if this value makes sense).
168 sample->tos = Memory::Address_at(sample->sp);
169 sample->has_external_callback = false;
ager@chromium.org01beca72009-11-24 14:29:16 +0000170 }
171
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000172 SafeStackTraceFrameIterator it(isolate,
173 sample->fp, sample->sp,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000174 sample->sp, js_entry_sp);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000175 int i = 0;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000176 while (!it.done() && i < TickSample::kMaxFramesCount) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000177 sample->stack[i++] = it.frame()->pc();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000178 it.Advance();
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000179 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000180 sample->frames_count = i;
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000181}
182
183
184//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000185// Ticker used to provide ticks to the profiler and the sliding state
186// window.
187//
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000188class Ticker: public Sampler {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000189 public:
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000190 Ticker(Isolate* isolate, int interval):
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000191 Sampler(isolate, interval),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000192 window_(NULL),
193 profiler_(NULL) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000194
195 ~Ticker() { if (IsActive()) Stop(); }
196
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000197 virtual void Tick(TickSample* sample) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000198 if (profiler_) profiler_->Insert(sample);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000199 if (window_) window_->AddState(sample->state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200 }
201
202 void SetWindow(SlidingStateWindow* window) {
203 window_ = window;
204 if (!IsActive()) Start();
205 }
206
207 void ClearWindow() {
208 window_ = NULL;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000209 if (!profiler_ && IsActive() && !RuntimeProfiler::IsEnabled()) Stop();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000210 }
211
212 void SetProfiler(Profiler* profiler) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000213 ASSERT(profiler_ == NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214 profiler_ = profiler;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000215 IncreaseProfilingDepth();
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000216 if (!FLAG_prof_lazy && !IsActive()) Start();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000217 }
218
219 void ClearProfiler() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000220 DecreaseProfilingDepth();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000221 profiler_ = NULL;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000222 if (!window_ && IsActive() && !RuntimeProfiler::IsEnabled()) Stop();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223 }
224
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000225 protected:
226 virtual void DoSampleStack(TickSample* sample) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000227 StackTracer::Trace(isolate(), sample);
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000228 }
229
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000230 private:
231 SlidingStateWindow* window_;
232 Profiler* profiler_;
233};
234
235
236//
237// SlidingStateWindow implementation.
238//
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000239SlidingStateWindow::SlidingStateWindow(Isolate* isolate)
240 : counters_(isolate->counters()), current_index_(0), is_full_(false) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000241 for (int i = 0; i < kBufferSize; i++) {
242 buffer_[i] = static_cast<byte>(OTHER);
243 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000244 isolate->logger()->ticker_->SetWindow(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000245}
246
247
248SlidingStateWindow::~SlidingStateWindow() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000249 LOGGER->ticker_->ClearWindow();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000250}
251
252
253void SlidingStateWindow::AddState(StateTag state) {
254 if (is_full_) {
255 DecrementStateCounter(static_cast<StateTag>(buffer_[current_index_]));
256 } else if (current_index_ == kBufferSize - 1) {
257 is_full_ = true;
258 }
259 buffer_[current_index_] = static_cast<byte>(state);
260 IncrementStateCounter(state);
261 ASSERT(IsPowerOf2(kBufferSize));
262 current_index_ = (current_index_ + 1) & (kBufferSize - 1);
263}
264
265
266//
267// Profiler implementation.
268//
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000269Profiler::Profiler(Isolate* isolate)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000270 : Thread("v8:Profiler"),
271 isolate_(isolate),
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000272 head_(0),
ager@chromium.org3811b432009-10-28 14:53:37 +0000273 tail_(0),
274 overflow_(false),
275 buffer_semaphore_(OS::CreateSemaphore(0)),
276 engaged_(false),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000277 running_(false),
278 paused_(false) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279}
280
281
282void Profiler::Engage() {
ager@chromium.org3811b432009-10-28 14:53:37 +0000283 if (engaged_) return;
284 engaged_ = true;
285
286 // TODO(mnaganov): This is actually "Chromium" mode. Flags need to be revised.
287 // http://code.google.com/p/v8/issues/detail?id=487
288 if (!FLAG_prof_lazy) {
289 OS::LogSharedLibraryAddresses();
290 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000291
292 // Start thread processing the profiler buffer.
293 running_ = true;
294 Start();
295
296 // Register to get ticks.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000297 LOGGER->ticker_->SetProfiler(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000298
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000299 LOGGER->ProfilerBeginEvent();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000300}
301
302
303void Profiler::Disengage() {
ager@chromium.org3811b432009-10-28 14:53:37 +0000304 if (!engaged_) return;
305
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000306 // Stop receiving ticks.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000307 LOGGER->ticker_->ClearProfiler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000308
309 // Terminate the worker thread by setting running_ to false,
310 // inserting a fake element in the queue and then wait for
311 // the thread to terminate.
312 running_ = false;
313 TickSample sample;
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000314 // Reset 'paused_' flag, otherwise semaphore may not be signalled.
315 resume();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000316 Insert(&sample);
317 Join();
318
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000319 LOG(ISOLATE, UncheckedStringEvent("profiler", "end"));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000320}
321
322
323void Profiler::Run() {
324 TickSample sample;
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000325 bool overflow = Remove(&sample);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000326 while (running_) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000327 LOG(isolate_, TickEvent(&sample, overflow));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000328 overflow = Remove(&sample);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000329 }
330}
331
332
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000333// Low-level profiling event structures.
334
335struct LowLevelCodeCreateStruct {
336 static const char kTag = 'C';
337
338 int32_t name_size;
339 Address code_address;
340 int32_t code_size;
341};
342
343
344struct LowLevelCodeMoveStruct {
345 static const char kTag = 'M';
346
347 Address from_address;
348 Address to_address;
349};
350
351
352struct LowLevelCodeDeleteStruct {
353 static const char kTag = 'D';
354
355 Address address;
356};
357
358
359struct LowLevelSnapshotPositionStruct {
360 static const char kTag = 'P';
361
362 Address address;
363 int32_t position;
364};
365
366
367static const char kCodeMovingGCTag = 'G';
368
369
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000370//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000371// Logger class implementation.
372//
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000373
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000374class Logger::NameMap {
375 public:
376 NameMap() : impl_(&PointerEquals) {}
377
378 ~NameMap() {
379 for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) {
380 DeleteArray(static_cast<const char*>(p->value));
381 }
382 }
383
384 void Insert(Address code_address, const char* name, int name_size) {
385 HashMap::Entry* entry = FindOrCreateEntry(code_address);
386 if (entry->value == NULL) {
387 entry->value = CopyName(name, name_size);
388 }
389 }
390
391 const char* Lookup(Address code_address) {
392 HashMap::Entry* entry = FindEntry(code_address);
393 return (entry != NULL) ? static_cast<const char*>(entry->value) : NULL;
394 }
395
396 void Remove(Address code_address) {
397 HashMap::Entry* entry = FindEntry(code_address);
ager@chromium.org04921a82011-06-27 13:21:41 +0000398 if (entry != NULL) {
399 DeleteArray(static_cast<char*>(entry->value));
400 RemoveEntry(entry);
401 }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000402 }
403
404 void Move(Address from, Address to) {
405 if (from == to) return;
406 HashMap::Entry* from_entry = FindEntry(from);
407 ASSERT(from_entry != NULL);
408 void* value = from_entry->value;
409 RemoveEntry(from_entry);
410 HashMap::Entry* to_entry = FindOrCreateEntry(to);
411 ASSERT(to_entry->value == NULL);
412 to_entry->value = value;
413 }
414
415 private:
416 static bool PointerEquals(void* lhs, void* rhs) {
417 return lhs == rhs;
418 }
419
420 static char* CopyName(const char* name, int name_size) {
421 char* result = NewArray<char>(name_size + 1);
422 for (int i = 0; i < name_size; ++i) {
423 char c = name[i];
424 if (c == '\0') c = ' ';
425 result[i] = c;
426 }
427 result[name_size] = '\0';
428 return result;
429 }
430
431 HashMap::Entry* FindOrCreateEntry(Address code_address) {
432 return impl_.Lookup(code_address, ComputePointerHash(code_address), true);
433 }
434
435 HashMap::Entry* FindEntry(Address code_address) {
436 return impl_.Lookup(code_address, ComputePointerHash(code_address), false);
437 }
438
439 void RemoveEntry(HashMap::Entry* entry) {
440 impl_.Remove(entry->key, entry->hash);
441 }
442
443 HashMap impl_;
444
445 DISALLOW_COPY_AND_ASSIGN(NameMap);
446};
447
448
449class Logger::NameBuffer {
450 public:
451 NameBuffer() { Reset(); }
452
453 void Reset() {
454 utf8_pos_ = 0;
455 }
456
457 void AppendString(String* str) {
458 if (str == NULL) return;
459 if (str->HasOnlyAsciiChars()) {
460 int utf8_length = Min(str->length(), kUtf8BufferSize - utf8_pos_);
461 String::WriteToFlat(str, utf8_buffer_ + utf8_pos_, 0, utf8_length);
462 utf8_pos_ += utf8_length;
463 return;
464 }
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000465 int uc16_length = Min(str->length(), kUtf16BufferSize);
466 String::WriteToFlat(str, utf16_buffer, 0, uc16_length);
467 int previous = unibrow::Utf16::kNoPreviousCharacter;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000468 for (int i = 0; i < uc16_length && utf8_pos_ < kUtf8BufferSize; ++i) {
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000469 uc16 c = utf16_buffer[i];
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000470 if (c <= String::kMaxAsciiCharCodeU) {
471 utf8_buffer_[utf8_pos_++] = static_cast<char>(c);
472 } else {
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000473 int char_length = unibrow::Utf8::Length(c, previous);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000474 if (utf8_pos_ + char_length > kUtf8BufferSize) break;
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000475 unibrow::Utf8::Encode(utf8_buffer_ + utf8_pos_, c, previous);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000476 utf8_pos_ += char_length;
477 }
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000478 previous = c;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000479 }
480 }
481
482 void AppendBytes(const char* bytes, int size) {
483 size = Min(size, kUtf8BufferSize - utf8_pos_);
484 memcpy(utf8_buffer_ + utf8_pos_, bytes, size);
485 utf8_pos_ += size;
486 }
487
488 void AppendBytes(const char* bytes) {
489 AppendBytes(bytes, StrLength(bytes));
490 }
491
492 void AppendByte(char c) {
493 if (utf8_pos_ >= kUtf8BufferSize) return;
494 utf8_buffer_[utf8_pos_++] = c;
495 }
496
497 void AppendInt(int n) {
498 Vector<char> buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_);
499 int size = OS::SNPrintF(buffer, "%d", n);
500 if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
501 utf8_pos_ += size;
502 }
503 }
504
505 const char* get() { return utf8_buffer_; }
506 int size() const { return utf8_pos_; }
507
508 private:
509 static const int kUtf8BufferSize = 512;
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000510 static const int kUtf16BufferSize = 128;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000511
512 int utf8_pos_;
513 char utf8_buffer_[kUtf8BufferSize];
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000514 uc16 utf16_buffer[kUtf16BufferSize];
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000515};
516
517
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000518Logger::Logger()
519 : ticker_(NULL),
520 profiler_(NULL),
521 sliding_state_window_(NULL),
522 log_events_(NULL),
523 logging_nesting_(0),
524 cpu_profiler_nesting_(0),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000525 log_(new Log(this)),
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000526 name_buffer_(new NameBuffer),
527 address_to_name_map_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000528 is_initialized_(false),
529 last_address_(NULL),
530 prev_sp_(NULL),
531 prev_function_(NULL),
532 prev_to_(NULL),
533 prev_code_(NULL) {
534}
535
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000536
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000537Logger::~Logger() {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000538 delete address_to_name_map_;
539 delete name_buffer_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000540 delete log_;
541}
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000542
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000543
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000544#define DECLARE_EVENT(ignore1, name) name,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000545static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000546 LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000547};
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000548#undef DECLARE_EVENT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000549
ager@chromium.org9085a012009-05-11 19:22:57 +0000550
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000551void Logger::ProfilerBeginEvent() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000552 if (!log_->IsEnabled()) return;
553 LogMessageBuilder msg(this);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000554 msg.Append("profiler,\"begin\",%d\n", kSamplingIntervalMs);
555 msg.WriteToLogFile();
556}
557
ager@chromium.org381abbb2009-02-25 13:23:22 +0000558
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000559void Logger::StringEvent(const char* name, const char* value) {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000560 if (FLAG_log) UncheckedStringEvent(name, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000561}
562
563
ager@chromium.org6f10e412009-02-13 10:11:16 +0000564void Logger::UncheckedStringEvent(const char* name, const char* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000565 if (!log_->IsEnabled()) return;
566 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000567 msg.Append("%s,\"%s\"\n", name, value);
568 msg.WriteToLogFile();
ager@chromium.org6f10e412009-02-13 10:11:16 +0000569}
ager@chromium.org6f10e412009-02-13 10:11:16 +0000570
571
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000572void Logger::IntEvent(const char* name, int value) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000573 if (FLAG_log) UncheckedIntEvent(name, value);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000574}
575
576
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000577void Logger::IntPtrTEvent(const char* name, intptr_t value) {
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000578 if (FLAG_log) UncheckedIntPtrTEvent(name, value);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000579}
580
581
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000582void Logger::UncheckedIntEvent(const char* name, int value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000583 if (!log_->IsEnabled()) return;
584 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000585 msg.Append("%s,%d\n", name, value);
586 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000587}
588
589
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000590void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000591 if (!log_->IsEnabled()) return;
592 LogMessageBuilder msg(this);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000593 msg.Append("%s,%" V8_PTR_PREFIX "d\n", name, value);
594 msg.WriteToLogFile();
595}
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000596
597
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000598void Logger::HandleEvent(const char* name, Object** location) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000599 if (!log_->IsEnabled() || !FLAG_log_handles) return;
600 LogMessageBuilder msg(this);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000601 msg.Append("%s,0x%" V8PRIxPTR "\n", name, location);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000602 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000603}
604
605
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000606// ApiEvent is private so all the calls come from the Logger class. It is the
ager@chromium.org9085a012009-05-11 19:22:57 +0000607// caller's responsibility to ensure that log is enabled and that
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000608// FLAG_log_api is true.
609void Logger::ApiEvent(const char* format, ...) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000610 ASSERT(log_->IsEnabled() && FLAG_log_api);
611 LogMessageBuilder msg(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000612 va_list ap;
613 va_start(ap, format);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000614 msg.AppendVA(format, ap);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000615 va_end(ap);
616 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000617}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000618
619
620void Logger::ApiNamedSecurityCheck(Object* key) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000621 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000622 if (key->IsString()) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000623 SmartArrayPointer<char> str =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000624 String::cast(key)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
625 ApiEvent("api,check-security,\"%s\"\n", *str);
626 } else if (key->IsUndefined()) {
627 ApiEvent("api,check-security,undefined\n");
628 } else {
629 ApiEvent("api,check-security,['no-name']\n");
630 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000631}
632
633
634void Logger::SharedLibraryEvent(const char* library_path,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000635 uintptr_t start,
636 uintptr_t end) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000637 if (!log_->IsEnabled() || !FLAG_prof) return;
638 LogMessageBuilder msg(this);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000639 msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
640 library_path,
641 start,
642 end);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000643 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000644}
645
646
647void Logger::SharedLibraryEvent(const wchar_t* library_path,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000648 uintptr_t start,
649 uintptr_t end) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000650 if (!log_->IsEnabled() || !FLAG_prof) return;
651 LogMessageBuilder msg(this);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000652 msg.Append("shared-library,\"%ls\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
653 library_path,
654 start,
655 end);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000656 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000657}
658
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000659
ager@chromium.org236ad962008-09-25 09:45:57 +0000660void Logger::LogRegExpSource(Handle<JSRegExp> regexp) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000661 // Prints "/" + re.source + "/" +
662 // (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000663 LogMessageBuilder msg(this);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000664
665 Handle<Object> source = GetProperty(regexp, "source");
666 if (!source->IsString()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000667 msg.Append("no source");
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000668 return;
669 }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000670
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000671 switch (regexp->TypeTag()) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000672 case JSRegExp::ATOM:
ager@chromium.org381abbb2009-02-25 13:23:22 +0000673 msg.Append('a');
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000674 break;
675 default:
676 break;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000677 }
ager@chromium.org381abbb2009-02-25 13:23:22 +0000678 msg.Append('/');
679 msg.AppendDetailed(*Handle<String>::cast(source), false);
680 msg.Append('/');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000681
682 // global flag
683 Handle<Object> global = GetProperty(regexp, "global");
684 if (global->IsTrue()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000685 msg.Append('g');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000686 }
687 // ignorecase flag
688 Handle<Object> ignorecase = GetProperty(regexp, "ignoreCase");
689 if (ignorecase->IsTrue()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000690 msg.Append('i');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000691 }
692 // multiline flag
693 Handle<Object> multiline = GetProperty(regexp, "multiline");
694 if (multiline->IsTrue()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000695 msg.Append('m');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000696 }
ager@chromium.org381abbb2009-02-25 13:23:22 +0000697
698 msg.WriteToLogFile();
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000699}
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000700
701
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000702void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000703 if (!log_->IsEnabled() || !FLAG_log_regexp) return;
704 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000705 msg.Append("regexp-compile,");
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000706 LogRegExpSource(regexp);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000707 msg.Append(in_cache ? ",hit\n" : ",miss\n");
708 msg.WriteToLogFile();
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000709}
710
711
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000712void Logger::LogRuntime(Vector<const char> format, JSArray* args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000713 if (!log_->IsEnabled() || !FLAG_log_runtime) return;
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000714 HandleScope scope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000715 LogMessageBuilder msg(this);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000716 for (int i = 0; i < format.length(); i++) {
717 char c = format[i];
718 if (c == '%' && i <= format.length() - 2) {
719 i++;
720 ASSERT('0' <= format[i] && format[i] <= '9');
lrn@chromium.org303ada72010-10-27 09:33:13 +0000721 MaybeObject* maybe = args->GetElement(format[i] - '0');
722 Object* obj;
723 if (!maybe->ToObject(&obj)) {
724 msg.Append("<exception>");
725 continue;
726 }
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000727 i++;
728 switch (format[i]) {
729 case 's':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000730 msg.AppendDetailed(String::cast(obj), false);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000731 break;
732 case 'S':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000733 msg.AppendDetailed(String::cast(obj), true);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000734 break;
735 case 'r':
736 Logger::LogRegExpSource(Handle<JSRegExp>(JSRegExp::cast(obj)));
737 break;
738 case 'x':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000739 msg.Append("0x%x", Smi::cast(obj)->value());
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000740 break;
741 case 'i':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000742 msg.Append("%i", Smi::cast(obj)->value());
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000743 break;
744 default:
745 UNREACHABLE();
746 }
747 } else {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000748 msg.Append(c);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000749 }
750 }
ager@chromium.org381abbb2009-02-25 13:23:22 +0000751 msg.Append('\n');
752 msg.WriteToLogFile();
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000753}
754
755
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000756void Logger::ApiIndexedSecurityCheck(uint32_t index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000757 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000758 ApiEvent("api,check-security,%u\n", index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000759}
760
761
762void Logger::ApiNamedPropertyAccess(const char* tag,
763 JSObject* holder,
764 Object* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000765 ASSERT(name->IsString());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000766 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000767 String* class_name_obj = holder->class_name();
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000768 SmartArrayPointer<char> class_name =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000769 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000770 SmartArrayPointer<char> property_name =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000771 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000772 ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000773}
774
775void Logger::ApiIndexedPropertyAccess(const char* tag,
776 JSObject* holder,
777 uint32_t index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000778 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000779 String* class_name_obj = holder->class_name();
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000780 SmartArrayPointer<char> class_name =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000781 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000782 ApiEvent("api,%s,\"%s\",%u\n", tag, *class_name, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000783}
784
785void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000786 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000787 String* class_name_obj = object->class_name();
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000788 SmartArrayPointer<char> class_name =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000789 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000790 ApiEvent("api,%s,\"%s\"\n", tag, *class_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000791}
792
793
794void Logger::ApiEntryCall(const char* name) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000795 if (!log_->IsEnabled() || !FLAG_log_api) return;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000796 ApiEvent("api,%s\n", name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000797}
798
799
800void Logger::NewEvent(const char* name, void* object, size_t size) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000801 if (!log_->IsEnabled() || !FLAG_log) return;
802 LogMessageBuilder msg(this);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000803 msg.Append("new,%s,0x%" V8PRIxPTR ",%u\n", name, object,
ager@chromium.org381abbb2009-02-25 13:23:22 +0000804 static_cast<unsigned int>(size));
805 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000806}
807
808
809void Logger::DeleteEvent(const char* name, void* object) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000810 if (!log_->IsEnabled() || !FLAG_log) return;
811 LogMessageBuilder msg(this);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000812 msg.Append("delete,%s,0x%" V8PRIxPTR "\n", name, object);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000813 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000814}
815
816
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000817void Logger::NewEventStatic(const char* name, void* object, size_t size) {
818 LOGGER->NewEvent(name, object, size);
819}
820
821
822void Logger::DeleteEventStatic(const char* name, void* object) {
823 LOGGER->DeleteEvent(name, object);
824}
825
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000826void Logger::CallbackEventInternal(const char* prefix, const char* name,
827 Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000828 if (!log_->IsEnabled() || !FLAG_log_code) return;
829 LogMessageBuilder msg(this);
ager@chromium.org01beca72009-11-24 14:29:16 +0000830 msg.Append("%s,%s,",
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000831 kLogEventsNames[CODE_CREATION_EVENT],
832 kLogEventsNames[CALLBACK_TAG]);
ager@chromium.org01beca72009-11-24 14:29:16 +0000833 msg.AppendAddress(entry_point);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000834 msg.Append(",1,\"%s%s\"", prefix, name);
ager@chromium.org01beca72009-11-24 14:29:16 +0000835 msg.Append('\n');
836 msg.WriteToLogFile();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000837}
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000838
839
840void Logger::CallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000841 if (!log_->IsEnabled() || !FLAG_log_code) return;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000842 SmartArrayPointer<char> str =
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000843 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
844 CallbackEventInternal("", *str, entry_point);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000845}
846
847
848void Logger::GetterCallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000849 if (!log_->IsEnabled() || !FLAG_log_code) return;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000850 SmartArrayPointer<char> str =
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000851 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
852 CallbackEventInternal("get ", *str, entry_point);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000853}
854
855
856void Logger::SetterCallbackEvent(String* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000857 if (!log_->IsEnabled() || !FLAG_log_code) return;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000858 SmartArrayPointer<char> str =
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000859 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
860 CallbackEventInternal("set ", *str, entry_point);
ager@chromium.org01beca72009-11-24 14:29:16 +0000861}
862
863
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000864void Logger::CodeCreateEvent(LogEventsAndTags tag,
865 Code* code,
866 const char* comment) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000867 if (!log_->IsEnabled()) return;
868 if (FLAG_ll_prof || Serializer::enabled()) {
869 name_buffer_->Reset();
870 name_buffer_->AppendBytes(kLogEventsNames[tag]);
871 name_buffer_->AppendByte(':');
872 name_buffer_->AppendBytes(comment);
873 }
874 if (FLAG_ll_prof) {
875 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
876 }
877 if (Serializer::enabled()) {
878 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
879 }
880 if (!FLAG_log_code) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000881 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000882 msg.Append("%s,%s,",
883 kLogEventsNames[CODE_CREATION_EVENT],
884 kLogEventsNames[tag]);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000885 msg.AppendAddress(code->address());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000886 msg.Append(",%d,\"", code->ExecutableSize());
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000887 for (const char* p = comment; *p != '\0'; p++) {
888 if (*p == '"') {
889 msg.Append('\\');
890 }
891 msg.Append(*p);
892 }
893 msg.Append('"');
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000894 msg.Append('\n');
895 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000896}
897
898
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000899void Logger::CodeCreateEvent(LogEventsAndTags tag,
900 Code* code,
901 String* name) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000902 if (!log_->IsEnabled()) return;
903 if (FLAG_ll_prof || Serializer::enabled()) {
904 name_buffer_->Reset();
905 name_buffer_->AppendBytes(kLogEventsNames[tag]);
906 name_buffer_->AppendByte(':');
907 name_buffer_->AppendString(name);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000908 }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000909 if (FLAG_ll_prof) {
910 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
911 }
912 if (Serializer::enabled()) {
913 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
914 }
915 if (!FLAG_log_code) return;
916 LogMessageBuilder msg(this);
917 msg.Append("%s,%s,",
918 kLogEventsNames[CODE_CREATION_EVENT],
919 kLogEventsNames[tag]);
920 msg.AppendAddress(code->address());
921 msg.Append(",%d,\"", code->ExecutableSize());
922 msg.AppendDetailed(name, false);
923 msg.Append('"');
924 msg.Append('\n');
925 msg.WriteToLogFile();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000926}
927
928
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000929// ComputeMarker must only be used when SharedFunctionInfo is known.
930static const char* ComputeMarker(Code* code) {
931 switch (code->kind()) {
932 case Code::FUNCTION: return code->optimizable() ? "~" : "";
933 case Code::OPTIMIZED_FUNCTION: return "*";
934 default: return "";
935 }
936}
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000937
938
939void Logger::CodeCreateEvent(LogEventsAndTags tag,
940 Code* code,
941 SharedFunctionInfo* shared,
942 String* name) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000943 if (!log_->IsEnabled()) return;
944 if (FLAG_ll_prof || Serializer::enabled()) {
945 name_buffer_->Reset();
946 name_buffer_->AppendBytes(kLogEventsNames[tag]);
947 name_buffer_->AppendByte(':');
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000948 name_buffer_->AppendBytes(ComputeMarker(code));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000949 name_buffer_->AppendString(name);
950 }
951 if (FLAG_ll_prof) {
952 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
953 }
954 if (Serializer::enabled()) {
955 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
956 }
957 if (!FLAG_log_code) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000958 if (code == Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000959 Builtins::kLazyCompile))
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000960 return;
961
962 LogMessageBuilder msg(this);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000963 SmartArrayPointer<char> str =
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000964 name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000965 msg.Append("%s,%s,",
966 kLogEventsNames[CODE_CREATION_EVENT],
967 kLogEventsNames[tag]);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000968 msg.AppendAddress(code->address());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000969 msg.Append(",%d,\"%s\",", code->ExecutableSize(), *str);
970 msg.AppendAddress(shared->address());
971 msg.Append(",%s", ComputeMarker(code));
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000972 msg.Append('\n');
973 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000974}
975
976
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000977// Although, it is possible to extract source and line from
978// the SharedFunctionInfo object, we left it to caller
979// to leave logging functions free from heap allocations.
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000980void Logger::CodeCreateEvent(LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000981 Code* code,
982 SharedFunctionInfo* shared,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000983 String* source, int line) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000984 if (!log_->IsEnabled()) return;
985 if (FLAG_ll_prof || Serializer::enabled()) {
986 name_buffer_->Reset();
987 name_buffer_->AppendBytes(kLogEventsNames[tag]);
988 name_buffer_->AppendByte(':');
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000989 name_buffer_->AppendBytes(ComputeMarker(code));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000990 name_buffer_->AppendString(shared->DebugName());
991 name_buffer_->AppendByte(' ');
992 name_buffer_->AppendString(source);
993 name_buffer_->AppendByte(':');
994 name_buffer_->AppendInt(line);
995 }
996 if (FLAG_ll_prof) {
997 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
998 }
999 if (Serializer::enabled()) {
1000 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
1001 }
1002 if (!FLAG_log_code) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001003 LogMessageBuilder msg(this);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001004 SmartArrayPointer<char> name =
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001005 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001006 SmartArrayPointer<char> sourcestr =
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001007 source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001008 msg.Append("%s,%s,",
1009 kLogEventsNames[CODE_CREATION_EVENT],
1010 kLogEventsNames[tag]);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001011 msg.AppendAddress(code->address());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001012 msg.Append(",%d,\"%s %s:%d\",",
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001013 code->ExecutableSize(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001014 *name,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001015 *sourcestr,
1016 line);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001017 msg.AppendAddress(shared->address());
1018 msg.Append(",%s", ComputeMarker(code));
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001019 msg.Append('\n');
1020 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001021}
1022
1023
1024void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001025 if (!log_->IsEnabled()) return;
1026 if (FLAG_ll_prof || Serializer::enabled()) {
1027 name_buffer_->Reset();
1028 name_buffer_->AppendBytes(kLogEventsNames[tag]);
1029 name_buffer_->AppendByte(':');
1030 name_buffer_->AppendInt(args_count);
1031 }
1032 if (FLAG_ll_prof) {
1033 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
1034 }
1035 if (Serializer::enabled()) {
1036 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
1037 }
1038 if (!FLAG_log_code) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001039 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001040 msg.Append("%s,%s,",
1041 kLogEventsNames[CODE_CREATION_EVENT],
1042 kLogEventsNames[tag]);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001043 msg.AppendAddress(code->address());
1044 msg.Append(",%d,\"args_count: %d\"", code->ExecutableSize(), args_count);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001045 msg.Append('\n');
1046 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001047}
1048
1049
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001050void Logger::CodeMovingGCEvent() {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001051 if (!log_->IsEnabled() || !FLAG_ll_prof) return;
1052 LowLevelLogWriteBytes(&kCodeMovingGCTag, sizeof(kCodeMovingGCTag));
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001053 OS::SignalCodeMovingGC();
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001054}
1055
1056
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001057void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001058 if (!log_->IsEnabled()) return;
1059 if (FLAG_ll_prof || Serializer::enabled()) {
1060 name_buffer_->Reset();
1061 name_buffer_->AppendBytes(kLogEventsNames[REG_EXP_TAG]);
1062 name_buffer_->AppendByte(':');
1063 name_buffer_->AppendString(source);
1064 }
1065 if (FLAG_ll_prof) {
1066 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
1067 }
1068 if (Serializer::enabled()) {
1069 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
1070 }
1071 if (!FLAG_log_code) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001072 LogMessageBuilder msg(this);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001073 msg.Append("%s,%s,",
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001074 kLogEventsNames[CODE_CREATION_EVENT],
1075 kLogEventsNames[REG_EXP_TAG]);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001076 msg.AppendAddress(code->address());
1077 msg.Append(",%d,\"", code->ExecutableSize());
1078 msg.AppendDetailed(source, false);
1079 msg.Append('\"');
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001080 msg.Append('\n');
1081 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001082}
1083
1084
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001085void Logger::CodeMoveEvent(Address from, Address to) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001086 if (!log_->IsEnabled()) return;
1087 if (FLAG_ll_prof) LowLevelCodeMoveEvent(from, to);
1088 if (Serializer::enabled() && address_to_name_map_ != NULL) {
1089 address_to_name_map_->Move(from, to);
1090 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001091 MoveEventInternal(CODE_MOVE_EVENT, from, to);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001092}
1093
1094
1095void Logger::CodeDeleteEvent(Address from) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001096 if (!log_->IsEnabled()) return;
1097 if (FLAG_ll_prof) LowLevelCodeDeleteEvent(from);
1098 if (Serializer::enabled() && address_to_name_map_ != NULL) {
1099 address_to_name_map_->Remove(from);
1100 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001101 DeleteEventInternal(CODE_DELETE_EVENT, from);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001102}
1103
1104
1105void Logger::SnapshotPositionEvent(Address addr, int pos) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001106 if (!log_->IsEnabled()) return;
1107 if (FLAG_ll_prof) LowLevelSnapshotPositionEvent(addr, pos);
1108 if (Serializer::enabled() && address_to_name_map_ != NULL) {
1109 const char* code_name = address_to_name_map_->Lookup(addr);
1110 if (code_name == NULL) return; // Not a code object.
1111 LogMessageBuilder msg(this);
1112 msg.Append("%s,%d,\"", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
1113 for (const char* p = code_name; *p != '\0'; ++p) {
1114 if (*p == '"') msg.Append('\\');
1115 msg.Append(*p);
1116 }
1117 msg.Append("\"\n");
1118 msg.WriteToLogFile();
1119 }
1120 if (!FLAG_log_snapshot_positions) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001121 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001122 msg.Append("%s,", kLogEventsNames[SNAPSHOT_POSITION_EVENT]);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001123 msg.AppendAddress(addr);
1124 msg.Append(",%d", pos);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001125 msg.Append('\n');
1126 msg.WriteToLogFile();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001127}
1128
1129
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001130void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001131 MoveEventInternal(SHARED_FUNC_MOVE_EVENT, from, to);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001132}
1133
1134
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001135void Logger::MoveEventInternal(LogEventsAndTags event,
1136 Address from,
1137 Address to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001138 if (!log_->IsEnabled() || !FLAG_log_code) return;
1139 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001140 msg.Append("%s,", kLogEventsNames[event]);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001141 msg.AppendAddress(from);
1142 msg.Append(',');
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001143 msg.AppendAddress(to);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001144 msg.Append('\n');
ager@chromium.org381abbb2009-02-25 13:23:22 +00001145 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001146}
1147
1148
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001149void Logger::DeleteEventInternal(LogEventsAndTags event, Address from) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001150 if (!log_->IsEnabled() || !FLAG_log_code) return;
1151 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001152 msg.Append("%s,", kLogEventsNames[event]);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001153 msg.AppendAddress(from);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001154 msg.Append('\n');
ager@chromium.org381abbb2009-02-25 13:23:22 +00001155 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001156}
1157
1158
1159void Logger::ResourceEvent(const char* name, const char* tag) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001160 if (!log_->IsEnabled() || !FLAG_log) return;
1161 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001162 msg.Append("%s,%s,", name, tag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001163
1164 uint32_t sec, usec;
1165 if (OS::GetUserTime(&sec, &usec) != -1) {
ager@chromium.org381abbb2009-02-25 13:23:22 +00001166 msg.Append("%d,%d,", sec, usec);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001167 }
ager@chromium.org381abbb2009-02-25 13:23:22 +00001168 msg.Append("%.0f", OS::TimeCurrentMillis());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001169
ager@chromium.org381abbb2009-02-25 13:23:22 +00001170 msg.Append('\n');
1171 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001172}
1173
1174
ager@chromium.org8bb60582008-12-11 12:02:20 +00001175void Logger::SuspectReadEvent(String* name, Object* obj) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001176 if (!log_->IsEnabled() || !FLAG_log_suspect) return;
1177 LogMessageBuilder msg(this);
ager@chromium.org8bb60582008-12-11 12:02:20 +00001178 String* class_name = obj->IsJSObject()
1179 ? JSObject::cast(obj)->class_name()
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001180 : HEAP->empty_string();
ager@chromium.org381abbb2009-02-25 13:23:22 +00001181 msg.Append("suspect-read,");
1182 msg.Append(class_name);
1183 msg.Append(',');
1184 msg.Append('"');
1185 msg.Append(name);
1186 msg.Append('"');
1187 msg.Append('\n');
1188 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001189}
1190
1191
1192void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001193 if (!log_->IsEnabled() || !FLAG_log_gc) return;
1194 LogMessageBuilder msg(this);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001195 // Using non-relative system time in order to be able to synchronize with
1196 // external memory profiling events (e.g. DOM memory size).
1197 msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f\n",
1198 space, kind, OS::TimeCurrentMillis());
1199 msg.WriteToLogFile();
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001200}
1201
1202
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001203void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001204 if (!log_->IsEnabled() || !FLAG_log_gc) return;
1205 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001206 msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind);
1207 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001208}
1209
1210
1211void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001212 if (!log_->IsEnabled() || !FLAG_log_gc) return;
1213 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001214 msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes);
1215 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001216}
1217
1218
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001219void Logger::DebugTag(const char* call_site_tag) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001220 if (!log_->IsEnabled() || !FLAG_log) return;
1221 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001222 msg.Append("debug-tag,%s\n", call_site_tag);
1223 msg.WriteToLogFile();
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001224}
1225
1226
1227void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001228 if (!log_->IsEnabled() || !FLAG_log) return;
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001229 StringBuilder s(parameter.length() + 1);
1230 for (int i = 0; i < parameter.length(); ++i) {
1231 s.AddCharacter(static_cast<char>(parameter[i]));
1232 }
1233 char* parameter_string = s.Finalize();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001234 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001235 msg.Append("debug-queue-event,%s,%15.3f,%s\n",
1236 event_type,
1237 OS::TimeCurrentMillis(),
1238 parameter_string);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001239 DeleteArray(parameter_string);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001240 msg.WriteToLogFile();
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001241}
1242
1243
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001244void Logger::TickEvent(TickSample* sample, bool overflow) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001245 if (!log_->IsEnabled() || !FLAG_prof) return;
1246 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001247 msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
1248 msg.AppendAddress(sample->pc);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001249 msg.Append(',');
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001250 msg.AppendAddress(sample->sp);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001251 if (sample->has_external_callback) {
1252 msg.Append(",1,");
1253 msg.AppendAddress(sample->external_callback);
1254 } else {
1255 msg.Append(",0,");
1256 msg.AppendAddress(sample->tos);
1257 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001258 msg.Append(",%d", static_cast<int>(sample->state));
ager@chromium.org381abbb2009-02-25 13:23:22 +00001259 if (overflow) {
1260 msg.Append(",overflow");
1261 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001262 for (int i = 0; i < sample->frames_count; ++i) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001263 msg.Append(',');
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001264 msg.AppendAddress(sample->stack[i]);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001265 }
1266 msg.Append('\n');
1267 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001268}
iposva@chromium.org245aa852009-02-10 00:49:54 +00001269
1270
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001271bool Logger::IsProfilerPaused() {
1272 return profiler_ == NULL || profiler_->paused();
iposva@chromium.org245aa852009-02-10 00:49:54 +00001273}
1274
1275
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001276void Logger::PauseProfiler() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001277 if (!log_->IsEnabled()) return;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001278 if (profiler_ != NULL) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001279 // It is OK to have negative nesting.
1280 if (--cpu_profiler_nesting_ == 0) {
1281 profiler_->pause();
1282 if (FLAG_prof_lazy) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001283 if (!FLAG_sliding_state_window && !RuntimeProfiler::IsEnabled()) {
1284 ticker_->Stop();
1285 }
ager@chromium.org5c838252010-02-19 08:53:10 +00001286 FLAG_log_code = false;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001287 LOG(ISOLATE, UncheckedStringEvent("profiler", "pause"));
ager@chromium.org5c838252010-02-19 08:53:10 +00001288 }
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001289 --logging_nesting_;
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00001290 }
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001291 }
iposva@chromium.org245aa852009-02-10 00:49:54 +00001292}
1293
1294
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001295void Logger::ResumeProfiler() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001296 if (!log_->IsEnabled()) return;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001297 if (profiler_ != NULL) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001298 if (cpu_profiler_nesting_++ == 0) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001299 ++logging_nesting_;
ager@chromium.org5c838252010-02-19 08:53:10 +00001300 if (FLAG_prof_lazy) {
1301 profiler_->Engage();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001302 LOG(ISOLATE, UncheckedStringEvent("profiler", "resume"));
ager@chromium.org5c838252010-02-19 08:53:10 +00001303 FLAG_log_code = true;
1304 LogCompiledFunctions();
ager@chromium.org5c838252010-02-19 08:53:10 +00001305 LogAccessorCallbacks();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001306 if (!FLAG_sliding_state_window && !ticker_->IsActive()) {
1307 ticker_->Start();
1308 }
ager@chromium.org5c838252010-02-19 08:53:10 +00001309 }
1310 profiler_->resume();
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00001311 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001312 }
iposva@chromium.org245aa852009-02-10 00:49:54 +00001313}
ager@chromium.org9085a012009-05-11 19:22:57 +00001314
1315
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001316// This function can be called when Log's mutex is acquired,
1317// either from main or Profiler's thread.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001318void Logger::LogFailure() {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001319 PauseProfiler();
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001320}
1321
1322
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001323bool Logger::IsProfilerSamplerActive() {
1324 return ticker_->IsActive();
1325}
1326
1327
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001328class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor {
1329 public:
1330 EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis,
1331 Handle<Code>* code_objects,
1332 int* count)
1333 : sfis_(sfis), code_objects_(code_objects), count_(count) { }
1334
1335 virtual void EnterContext(Context* context) {}
1336 virtual void LeaveContext(Context* context) {}
1337
1338 virtual void VisitFunction(JSFunction* function) {
whesse@chromium.org7b260152011-06-20 15:33:18 +00001339 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(function->shared());
1340 Object* maybe_script = sfi->script();
1341 if (maybe_script->IsScript()
1342 && !Script::cast(maybe_script)->HasValidSource()) return;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001343 if (sfis_ != NULL) {
whesse@chromium.org7b260152011-06-20 15:33:18 +00001344 sfis_[*count_] = Handle<SharedFunctionInfo>(sfi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001345 }
1346 if (code_objects_ != NULL) {
1347 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
1348 code_objects_[*count_] = Handle<Code>(function->code());
1349 }
1350 *count_ = *count_ + 1;
1351 }
1352
1353 private:
1354 Handle<SharedFunctionInfo>* sfis_;
1355 Handle<Code>* code_objects_;
1356 int* count_;
1357};
1358
1359
1360static int EnumerateCompiledFunctions(Handle<SharedFunctionInfo>* sfis,
1361 Handle<Code>* code_objects) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001362 HeapIterator iterator;
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001363 AssertNoAllocation no_alloc;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001364 int compiled_funcs_count = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001365
1366 // Iterate the heap to find shared function info objects and record
1367 // the unoptimized code for them.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001368 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001369 if (!obj->IsSharedFunctionInfo()) continue;
1370 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
1371 if (sfi->is_compiled()
1372 && (!sfi->script()->IsScript()
1373 || Script::cast(sfi->script())->HasValidSource())) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001374 if (sfis != NULL) {
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001375 sfis[compiled_funcs_count] = Handle<SharedFunctionInfo>(sfi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001376 }
1377 if (code_objects != NULL) {
1378 code_objects[compiled_funcs_count] = Handle<Code>(sfi->code());
1379 }
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001380 ++compiled_funcs_count;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001381 }
1382 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001383
1384 // Iterate all optimized functions in all contexts.
1385 EnumerateOptimizedFunctionsVisitor visitor(sfis,
1386 code_objects,
1387 &compiled_funcs_count);
1388 Deoptimizer::VisitAllOptimizedFunctions(&visitor);
1389
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001390 return compiled_funcs_count;
1391}
1392
1393
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001394void Logger::LogCodeObject(Object* object) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001395 if (FLAG_log_code || FLAG_ll_prof) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001396 Code* code_object = Code::cast(object);
1397 LogEventsAndTags tag = Logger::STUB_TAG;
1398 const char* description = "Unknown code from the snapshot";
1399 switch (code_object->kind()) {
1400 case Code::FUNCTION:
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001401 case Code::OPTIMIZED_FUNCTION:
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001402 return; // We log this later using LogCompiledFunctions.
danno@chromium.org40cb8782011-05-25 07:58:50 +00001403 case Code::UNARY_OP_IC: // fall through
1404 case Code::BINARY_OP_IC: // fall through
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001405 case Code::COMPARE_IC: // fall through
ricow@chromium.org9fa09672011-07-25 11:05:35 +00001406 case Code::TO_BOOLEAN_IC: // fall through
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001407 case Code::STUB:
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001408 description =
1409 CodeStub::MajorName(CodeStub::GetMajorKey(code_object), true);
ager@chromium.org5c838252010-02-19 08:53:10 +00001410 if (description == NULL)
1411 description = "A stub from the snapshot";
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001412 tag = Logger::STUB_TAG;
1413 break;
1414 case Code::BUILTIN:
1415 description = "A builtin from the snapshot";
1416 tag = Logger::BUILTIN_TAG;
1417 break;
1418 case Code::KEYED_LOAD_IC:
1419 description = "A keyed load IC from the snapshot";
1420 tag = Logger::KEYED_LOAD_IC_TAG;
1421 break;
1422 case Code::LOAD_IC:
1423 description = "A load IC from the snapshot";
1424 tag = Logger::LOAD_IC_TAG;
1425 break;
1426 case Code::STORE_IC:
1427 description = "A store IC from the snapshot";
1428 tag = Logger::STORE_IC_TAG;
1429 break;
1430 case Code::KEYED_STORE_IC:
1431 description = "A keyed store IC from the snapshot";
1432 tag = Logger::KEYED_STORE_IC_TAG;
1433 break;
1434 case Code::CALL_IC:
1435 description = "A call IC from the snapshot";
1436 tag = Logger::CALL_IC_TAG;
1437 break;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001438 case Code::KEYED_CALL_IC:
1439 description = "A keyed call IC from the snapshot";
1440 tag = Logger::KEYED_CALL_IC_TAG;
1441 break;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001442 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001443 PROFILE(ISOLATE, CodeCreateEvent(tag, code_object, description));
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001444 }
1445}
1446
1447
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001448void Logger::LogCodeInfo() {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001449 if (!log_->IsEnabled() || !FLAG_ll_prof) return;
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001450#if V8_TARGET_ARCH_IA32
1451 const char arch[] = "ia32";
1452#elif V8_TARGET_ARCH_X64
1453 const char arch[] = "x64";
1454#elif V8_TARGET_ARCH_ARM
1455 const char arch[] = "arm";
danno@chromium.orgc612e022011-11-10 11:38:15 +00001456#elif V8_TARGET_ARCH_MIPS
1457 const char arch[] = "mips";
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001458#else
1459 const char arch[] = "unknown";
1460#endif
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001461 LowLevelLogWriteBytes(arch, sizeof(arch));
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001462}
1463
1464
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001465void Logger::RegisterSnapshotCodeName(Code* code,
1466 const char* name,
1467 int name_size) {
1468 ASSERT(Serializer::enabled());
1469 if (address_to_name_map_ == NULL) {
1470 address_to_name_map_ = new NameMap;
1471 }
1472 address_to_name_map_->Insert(code->address(), name, name_size);
1473}
1474
1475
1476void Logger::LowLevelCodeCreateEvent(Code* code,
1477 const char* name,
1478 int name_size) {
1479 if (log_->ll_output_handle_ == NULL) return;
1480 LowLevelCodeCreateStruct event;
1481 event.name_size = name_size;
1482 event.code_address = code->instruction_start();
1483 ASSERT(event.code_address == code->address() + Code::kHeaderSize);
1484 event.code_size = code->instruction_size();
1485 LowLevelLogWriteStruct(event);
1486 LowLevelLogWriteBytes(name, name_size);
1487 LowLevelLogWriteBytes(
1488 reinterpret_cast<const char*>(code->instruction_start()),
1489 code->instruction_size());
1490}
1491
1492
1493void Logger::LowLevelCodeMoveEvent(Address from, Address to) {
1494 if (log_->ll_output_handle_ == NULL) return;
1495 LowLevelCodeMoveStruct event;
1496 event.from_address = from + Code::kHeaderSize;
1497 event.to_address = to + Code::kHeaderSize;
1498 LowLevelLogWriteStruct(event);
1499}
1500
1501
1502void Logger::LowLevelCodeDeleteEvent(Address from) {
1503 if (log_->ll_output_handle_ == NULL) return;
1504 LowLevelCodeDeleteStruct event;
1505 event.address = from + Code::kHeaderSize;
1506 LowLevelLogWriteStruct(event);
1507}
1508
1509
1510void Logger::LowLevelSnapshotPositionEvent(Address addr, int pos) {
1511 if (log_->ll_output_handle_ == NULL) return;
1512 LowLevelSnapshotPositionStruct event;
1513 event.address = addr + Code::kHeaderSize;
1514 event.position = pos;
1515 LowLevelLogWriteStruct(event);
1516}
1517
1518
1519void Logger::LowLevelLogWriteBytes(const char* bytes, int size) {
1520 size_t rv = fwrite(bytes, 1, size, log_->ll_output_handle_);
1521 ASSERT(static_cast<size_t>(size) == rv);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001522 USE(rv);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001523}
1524
1525
ager@chromium.org5c838252010-02-19 08:53:10 +00001526void Logger::LogCodeObjects() {
rossberg@chromium.org994edf62012-02-06 10:12:55 +00001527 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1528 "Logger::LogCodeObjects");
ager@chromium.org5c838252010-02-19 08:53:10 +00001529 HeapIterator iterator;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001530 AssertNoAllocation no_alloc;
ager@chromium.org5c838252010-02-19 08:53:10 +00001531 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1532 if (obj->IsCode()) LogCodeObject(obj);
1533 }
1534}
1535
1536
lrn@chromium.org34e60782011-09-15 07:25:40 +00001537void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
1538 Handle<Code> code) {
1539 Handle<String> func_name(shared->DebugName());
1540 if (shared->script()->IsScript()) {
1541 Handle<Script> script(Script::cast(shared->script()));
1542 if (script->name()->IsString()) {
1543 Handle<String> script_name(String::cast(script->name()));
1544 int line_num = GetScriptLineNumber(script, shared->start_position());
1545 if (line_num > 0) {
1546 PROFILE(ISOLATE,
1547 CodeCreateEvent(
1548 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
1549 *code, *shared,
1550 *script_name, line_num + 1));
1551 } else {
1552 // Can't distinguish eval and script here, so always use Script.
1553 PROFILE(ISOLATE,
1554 CodeCreateEvent(
1555 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
1556 *code, *shared, *script_name));
1557 }
1558 } else {
1559 PROFILE(ISOLATE,
1560 CodeCreateEvent(
1561 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
1562 *code, *shared, *func_name));
1563 }
1564 } else if (shared->IsApiFunction()) {
1565 // API function.
1566 FunctionTemplateInfo* fun_data = shared->get_api_func_data();
1567 Object* raw_call_data = fun_data->call_code();
1568 if (!raw_call_data->IsUndefined()) {
1569 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1570 Object* callback_obj = call_data->callback();
1571 Address entry_point = v8::ToCData<Address>(callback_obj);
1572 PROFILE(ISOLATE, CallbackEvent(*func_name, entry_point));
1573 }
1574 } else {
1575 PROFILE(ISOLATE,
1576 CodeCreateEvent(
1577 Logger::LAZY_COMPILE_TAG, *code, *shared, *func_name));
1578 }
1579}
1580
1581
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001582void Logger::LogCompiledFunctions() {
rossberg@chromium.org994edf62012-02-06 10:12:55 +00001583 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1584 "Logger::LogCompiledFunctions");
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001585 HandleScope scope;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001586 const int compiled_funcs_count = EnumerateCompiledFunctions(NULL, NULL);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001587 ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001588 ScopedVector< Handle<Code> > code_objects(compiled_funcs_count);
1589 EnumerateCompiledFunctions(sfis.start(), code_objects.start());
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001590
1591 // During iteration, there can be heap allocation due to
1592 // GetScriptLineNumber call.
1593 for (int i = 0; i < compiled_funcs_count; ++i) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001594 if (*code_objects[i] == Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001595 Builtins::kLazyCompile))
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001596 continue;
lrn@chromium.org34e60782011-09-15 07:25:40 +00001597 LogExistingFunction(sfis[i], code_objects[i]);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001598 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001599}
1600
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001601
1602void Logger::LogAccessorCallbacks() {
rossberg@chromium.org994edf62012-02-06 10:12:55 +00001603 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1604 "Logger::LogAccessorCallbacks");
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001605 HeapIterator iterator;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001606 AssertNoAllocation no_alloc;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001607 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001608 if (!obj->IsAccessorInfo()) continue;
1609 AccessorInfo* ai = AccessorInfo::cast(obj);
1610 if (!ai->name()->IsString()) continue;
1611 String* name = String::cast(ai->name());
1612 Address getter_entry = v8::ToCData<Address>(ai->getter());
1613 if (getter_entry != 0) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001614 PROFILE(ISOLATE, GetterCallbackEvent(name, getter_entry));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001615 }
1616 Address setter_entry = v8::ToCData<Address>(ai->setter());
1617 if (setter_entry != 0) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001618 PROFILE(ISOLATE, SetterCallbackEvent(name, setter_entry));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001619 }
1620 }
1621}
1622
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001623
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001624bool Logger::SetUp() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001625 // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
1626 if (is_initialized_) return true;
1627 is_initialized_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001628
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001629 // --ll-prof implies --log-code and --log-snapshot-positions.
1630 if (FLAG_ll_prof) {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001631 FLAG_log_snapshot_positions = true;
1632 }
1633
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001634 // --prof_lazy controls --log-code, implies --noprof_auto.
1635 if (FLAG_prof_lazy) {
1636 FLAG_log_code = false;
1637 FLAG_prof_auto = false;
1638 }
1639
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001640 // TODO(isolates): this assert introduces cyclic dependency (logger
1641 // -> thread local top -> heap -> logger).
1642 // ASSERT(VMState::is_outermost_external());
ager@chromium.org3e875802009-06-29 08:26:34 +00001643
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001644 log_->Initialize();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001645
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001646 if (FLAG_ll_prof) LogCodeInfo();
1647
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001648 Isolate* isolate = Isolate::Current();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001649 ticker_ = new Ticker(isolate, kSamplingIntervalMs);
1650
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001651 if (FLAG_sliding_state_window && sliding_state_window_ == NULL) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001652 sliding_state_window_ = new SlidingStateWindow(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001653 }
1654
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001655 bool start_logging = FLAG_log || FLAG_log_runtime || FLAG_log_api
1656 || FLAG_log_code || FLAG_log_gc || FLAG_log_handles || FLAG_log_suspect
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001657 || FLAG_log_regexp || FLAG_log_state_changes || FLAG_ll_prof;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001658
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001659 if (start_logging) {
1660 logging_nesting_ = 1;
1661 }
ager@chromium.org3e875802009-06-29 08:26:34 +00001662
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001663 if (FLAG_prof) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001664 profiler_ = new Profiler(isolate);
ager@chromium.org3e875802009-06-29 08:26:34 +00001665 if (!FLAG_prof_auto) {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001666 profiler_->pause();
ager@chromium.org3e875802009-06-29 08:26:34 +00001667 } else {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001668 logging_nesting_ = 1;
ager@chromium.org3e875802009-06-29 08:26:34 +00001669 }
ager@chromium.org3811b432009-10-28 14:53:37 +00001670 if (!FLAG_prof_lazy) {
1671 profiler_->Engage();
1672 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001673 }
1674
1675 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001676}
1677
1678
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001679Sampler* Logger::sampler() {
1680 return ticker_;
1681}
1682
1683
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001684void Logger::EnsureTickerStarted() {
1685 ASSERT(ticker_ != NULL);
1686 if (!ticker_->IsActive()) ticker_->Start();
1687}
1688
1689
1690void Logger::EnsureTickerStopped() {
1691 if (ticker_ != NULL && ticker_->IsActive()) ticker_->Stop();
1692}
1693
1694
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001695FILE* Logger::TearDown() {
1696 if (!is_initialized_) return NULL;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001697 is_initialized_ = false;
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001698
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001699 // Stop the profiler before closing the file.
1700 if (profiler_ != NULL) {
1701 profiler_->Disengage();
1702 delete profiler_;
1703 profiler_ = NULL;
1704 }
1705
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001706 delete sliding_state_window_;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001707 sliding_state_window_ = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001708
1709 delete ticker_;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001710 ticker_ = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001711
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001712 return log_->Close();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001713}
1714
1715
1716void Logger::EnableSlidingStateWindow() {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001717 // If the ticker is NULL, Logger::SetUp has not been called yet. In
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001718 // that case, we set the sliding_state_window flag so that the
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001719 // sliding window computation will be started when Logger::SetUp is
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001720 // called.
1721 if (ticker_ == NULL) {
1722 FLAG_sliding_state_window = true;
1723 return;
1724 }
1725 // Otherwise, if the sliding state window computation has not been
1726 // started we do it now.
1727 if (sliding_state_window_ == NULL) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001728 sliding_state_window_ = new SlidingStateWindow(Isolate::Current());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001729 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001730}
1731
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001732// Protects the state below.
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001733static Mutex* active_samplers_mutex = NULL;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001734
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001735List<Sampler*>* SamplerRegistry::active_samplers_ = NULL;
1736
1737
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001738void SamplerRegistry::SetUp() {
1739 if (!active_samplers_mutex) {
1740 active_samplers_mutex = OS::CreateMutex();
1741 }
1742}
1743
1744
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001745bool SamplerRegistry::IterateActiveSamplers(VisitSampler func, void* param) {
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001746 ScopedLock lock(active_samplers_mutex);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001747 for (int i = 0;
1748 ActiveSamplersExist() && i < active_samplers_->length();
1749 ++i) {
1750 func(active_samplers_->at(i), param);
1751 }
1752 return ActiveSamplersExist();
1753}
1754
1755
1756static void ComputeCpuProfiling(Sampler* sampler, void* flag_ptr) {
1757 bool* flag = reinterpret_cast<bool*>(flag_ptr);
1758 *flag |= sampler->IsProfiling();
1759}
1760
1761
1762SamplerRegistry::State SamplerRegistry::GetState() {
1763 bool flag = false;
1764 if (!IterateActiveSamplers(&ComputeCpuProfiling, &flag)) {
1765 return HAS_NO_SAMPLERS;
1766 }
1767 return flag ? HAS_CPU_PROFILING_SAMPLERS : HAS_SAMPLERS;
1768}
1769
1770
1771void SamplerRegistry::AddActiveSampler(Sampler* sampler) {
1772 ASSERT(sampler->IsActive());
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001773 ScopedLock lock(active_samplers_mutex);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001774 if (active_samplers_ == NULL) {
1775 active_samplers_ = new List<Sampler*>;
1776 } else {
1777 ASSERT(!active_samplers_->Contains(sampler));
1778 }
1779 active_samplers_->Add(sampler);
1780}
1781
1782
1783void SamplerRegistry::RemoveActiveSampler(Sampler* sampler) {
1784 ASSERT(sampler->IsActive());
fschneider@chromium.org7d10be52012-04-10 12:30:14 +00001785 ScopedLock lock(active_samplers_mutex);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001786 ASSERT(active_samplers_ != NULL);
1787 bool removed = active_samplers_->RemoveElement(sampler);
1788 ASSERT(removed);
1789 USE(removed);
1790}
1791
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001792} } // namespace v8::internal