blob: 82ce886fc9248cd31f49bca7e691b071bad4ff6c [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// The Profiler samples pc and sp values for the main thread.
48// Each sample is appended to a circular buffer.
49// An independent thread removes data and writes it to the log.
50// This design minimizes the time spent in the sampler.
51//
52class Profiler: public Thread {
53 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000054 explicit Profiler(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000055 void Engage();
56 void Disengage();
57
58 // Inserts collected profiling data into buffer.
59 void Insert(TickSample* sample) {
iposva@chromium.org245aa852009-02-10 00:49:54 +000060 if (paused_)
61 return;
62
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000063 if (Succ(head_) == tail_) {
64 overflow_ = true;
65 } else {
66 buffer_[head_] = *sample;
67 head_ = Succ(head_);
68 buffer_semaphore_->Signal(); // Tell we have an element.
69 }
70 }
71
72 // Waits for a signal and removes profiling data.
73 bool Remove(TickSample* sample) {
74 buffer_semaphore_->Wait(); // Wait for an element.
75 *sample = buffer_[tail_];
76 bool result = overflow_;
77 tail_ = Succ(tail_);
78 overflow_ = false;
79 return result;
80 }
81
82 void Run();
83
iposva@chromium.org245aa852009-02-10 00:49:54 +000084 // Pause and Resume TickSample data collection.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000085 bool paused() const { return paused_; }
86 void pause() { paused_ = true; }
87 void resume() { paused_ = false; }
iposva@chromium.org245aa852009-02-10 00:49:54 +000088
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000089 private:
90 // Returns the next index in the cyclic buffer.
91 int Succ(int index) { return (index + 1) % kBufferSize; }
92
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000093 Isolate* isolate_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000094 // Cyclic buffer for communicating profiling samples
95 // between the signal handler and the worker thread.
96 static const int kBufferSize = 128;
97 TickSample buffer_[kBufferSize]; // Buffer storage.
98 int head_; // Index to the buffer head.
99 int tail_; // Index to the buffer tail.
100 bool overflow_; // Tell whether a buffer overflow has occurred.
101 Semaphore* buffer_semaphore_; // Sempahore used for buffer synchronization.
102
ager@chromium.org3811b432009-10-28 14:53:37 +0000103 // Tells whether profiler is engaged, that is, processing thread is stated.
104 bool engaged_;
105
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000106 // Tells whether worker thread should continue running.
107 bool running_;
iposva@chromium.org245aa852009-02-10 00:49:54 +0000108
109 // Tells whether we are currently recording tick samples.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000110 bool paused_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000111};
112
113
114//
115// Ticker used to provide ticks to the profiler and the sliding state
116// window.
117//
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000118class Ticker: public Sampler {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000119 public:
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000120 Ticker(Isolate* isolate, int interval):
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000121 Sampler(isolate, interval),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000122 profiler_(NULL) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000123
124 ~Ticker() { if (IsActive()) Stop(); }
125
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000126 virtual void Tick(TickSample* sample) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000127 if (profiler_) profiler_->Insert(sample);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128 }
129
130 void SetProfiler(Profiler* profiler) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000131 ASSERT(profiler_ == NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000132 profiler_ = profiler;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000133 IncreaseProfilingDepth();
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000134 if (!FLAG_prof_lazy && !IsActive()) Start();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000135 }
136
137 void ClearProfiler() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000138 DecreaseProfilingDepth();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000139 profiler_ = NULL;
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +0000140 if (IsActive()) Stop();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000141 }
142
143 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000144 Profiler* profiler_;
145};
146
147
148//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000149// Profiler implementation.
150//
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000151Profiler::Profiler(Isolate* isolate)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000152 : Thread("v8:Profiler"),
153 isolate_(isolate),
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000154 head_(0),
ager@chromium.org3811b432009-10-28 14:53:37 +0000155 tail_(0),
156 overflow_(false),
157 buffer_semaphore_(OS::CreateSemaphore(0)),
158 engaged_(false),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000159 running_(false),
160 paused_(false) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000161}
162
163
164void Profiler::Engage() {
ager@chromium.org3811b432009-10-28 14:53:37 +0000165 if (engaged_) return;
166 engaged_ = true;
167
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000168 OS::LogSharedLibraryAddresses();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169
170 // Start thread processing the profiler buffer.
171 running_ = true;
172 Start();
173
174 // Register to get ticks.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000175 Logger* logger = isolate_->logger();
176 logger->ticker_->SetProfiler(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000177
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000178 logger->ProfilerBeginEvent();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000179}
180
181
182void Profiler::Disengage() {
ager@chromium.org3811b432009-10-28 14:53:37 +0000183 if (!engaged_) return;
184
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000185 // Stop receiving ticks.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000186 isolate_->logger()->ticker_->ClearProfiler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000187
188 // Terminate the worker thread by setting running_ to false,
189 // inserting a fake element in the queue and then wait for
190 // the thread to terminate.
191 running_ = false;
192 TickSample sample;
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000193 // Reset 'paused_' flag, otherwise semaphore may not be signalled.
194 resume();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195 Insert(&sample);
196 Join();
197
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000198 LOG(ISOLATE, UncheckedStringEvent("profiler", "end"));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000199}
200
201
202void Profiler::Run() {
203 TickSample sample;
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000204 bool overflow = Remove(&sample);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000205 while (running_) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000206 LOG(isolate_, TickEvent(&sample, overflow));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000207 overflow = Remove(&sample);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000208 }
209}
210
211
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000212// Low-level profiling event structures.
213
214struct LowLevelCodeCreateStruct {
215 static const char kTag = 'C';
216
217 int32_t name_size;
218 Address code_address;
219 int32_t code_size;
220};
221
222
223struct LowLevelCodeMoveStruct {
224 static const char kTag = 'M';
225
226 Address from_address;
227 Address to_address;
228};
229
230
231struct LowLevelCodeDeleteStruct {
232 static const char kTag = 'D';
233
234 Address address;
235};
236
237
238struct LowLevelSnapshotPositionStruct {
239 static const char kTag = 'P';
240
241 Address address;
242 int32_t position;
243};
244
245
246static const char kCodeMovingGCTag = 'G';
247
248
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000250// Logger class implementation.
251//
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000252
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000253class Logger::NameMap {
254 public:
255 NameMap() : impl_(&PointerEquals) {}
256
257 ~NameMap() {
258 for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) {
259 DeleteArray(static_cast<const char*>(p->value));
260 }
261 }
262
263 void Insert(Address code_address, const char* name, int name_size) {
264 HashMap::Entry* entry = FindOrCreateEntry(code_address);
265 if (entry->value == NULL) {
266 entry->value = CopyName(name, name_size);
267 }
268 }
269
270 const char* Lookup(Address code_address) {
271 HashMap::Entry* entry = FindEntry(code_address);
272 return (entry != NULL) ? static_cast<const char*>(entry->value) : NULL;
273 }
274
275 void Remove(Address code_address) {
276 HashMap::Entry* entry = FindEntry(code_address);
ager@chromium.org04921a82011-06-27 13:21:41 +0000277 if (entry != NULL) {
278 DeleteArray(static_cast<char*>(entry->value));
279 RemoveEntry(entry);
280 }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000281 }
282
283 void Move(Address from, Address to) {
284 if (from == to) return;
285 HashMap::Entry* from_entry = FindEntry(from);
286 ASSERT(from_entry != NULL);
287 void* value = from_entry->value;
288 RemoveEntry(from_entry);
289 HashMap::Entry* to_entry = FindOrCreateEntry(to);
290 ASSERT(to_entry->value == NULL);
291 to_entry->value = value;
292 }
293
294 private:
295 static bool PointerEquals(void* lhs, void* rhs) {
296 return lhs == rhs;
297 }
298
299 static char* CopyName(const char* name, int name_size) {
300 char* result = NewArray<char>(name_size + 1);
301 for (int i = 0; i < name_size; ++i) {
302 char c = name[i];
303 if (c == '\0') c = ' ';
304 result[i] = c;
305 }
306 result[name_size] = '\0';
307 return result;
308 }
309
310 HashMap::Entry* FindOrCreateEntry(Address code_address) {
311 return impl_.Lookup(code_address, ComputePointerHash(code_address), true);
312 }
313
314 HashMap::Entry* FindEntry(Address code_address) {
315 return impl_.Lookup(code_address, ComputePointerHash(code_address), false);
316 }
317
318 void RemoveEntry(HashMap::Entry* entry) {
319 impl_.Remove(entry->key, entry->hash);
320 }
321
322 HashMap impl_;
323
324 DISALLOW_COPY_AND_ASSIGN(NameMap);
325};
326
327
328class Logger::NameBuffer {
329 public:
330 NameBuffer() { Reset(); }
331
332 void Reset() {
333 utf8_pos_ = 0;
334 }
335
336 void AppendString(String* str) {
337 if (str == NULL) return;
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000338 int uc16_length = Min(str->length(), kUtf16BufferSize);
339 String::WriteToFlat(str, utf16_buffer, 0, uc16_length);
340 int previous = unibrow::Utf16::kNoPreviousCharacter;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000341 for (int i = 0; i < uc16_length && utf8_pos_ < kUtf8BufferSize; ++i) {
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000342 uc16 c = utf16_buffer[i];
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000343 if (c <= unibrow::Utf8::kMaxOneByteChar) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000344 utf8_buffer_[utf8_pos_++] = static_cast<char>(c);
345 } else {
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000346 int char_length = unibrow::Utf8::Length(c, previous);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000347 if (utf8_pos_ + char_length > kUtf8BufferSize) break;
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000348 unibrow::Utf8::Encode(utf8_buffer_ + utf8_pos_, c, previous);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000349 utf8_pos_ += char_length;
350 }
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000351 previous = c;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000352 }
353 }
354
355 void AppendBytes(const char* bytes, int size) {
356 size = Min(size, kUtf8BufferSize - utf8_pos_);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000357 OS::MemCopy(utf8_buffer_ + utf8_pos_, bytes, size);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000358 utf8_pos_ += size;
359 }
360
361 void AppendBytes(const char* bytes) {
362 AppendBytes(bytes, StrLength(bytes));
363 }
364
365 void AppendByte(char c) {
366 if (utf8_pos_ >= kUtf8BufferSize) return;
367 utf8_buffer_[utf8_pos_++] = c;
368 }
369
370 void AppendInt(int n) {
371 Vector<char> buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_);
372 int size = OS::SNPrintF(buffer, "%d", n);
373 if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
374 utf8_pos_ += size;
375 }
376 }
377
ulan@chromium.org750145a2013-03-07 15:14:13 +0000378 void AppendHex(uint32_t n) {
379 Vector<char> buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_);
380 int size = OS::SNPrintF(buffer, "%x", n);
381 if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
382 utf8_pos_ += size;
383 }
384 }
385
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000386 const char* get() { return utf8_buffer_; }
387 int size() const { return utf8_pos_; }
388
389 private:
390 static const int kUtf8BufferSize = 512;
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000391 static const int kUtf16BufferSize = 128;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000392
393 int utf8_pos_;
394 char utf8_buffer_[kUtf8BufferSize];
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000395 uc16 utf16_buffer[kUtf16BufferSize];
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000396};
397
398
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000399Logger::Logger(Isolate* isolate)
400 : isolate_(isolate),
401 ticker_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000402 profiler_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000403 log_events_(NULL),
404 logging_nesting_(0),
405 cpu_profiler_nesting_(0),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000406 log_(new Log(this)),
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000407 name_buffer_(new NameBuffer),
408 address_to_name_map_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000409 is_initialized_(false),
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000410 code_event_handler_(NULL),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000411 last_address_(NULL),
412 prev_sp_(NULL),
413 prev_function_(NULL),
414 prev_to_(NULL),
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000415 prev_code_(NULL),
416 epoch_(0) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000417}
418
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000419
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000420Logger::~Logger() {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000421 delete address_to_name_map_;
422 delete name_buffer_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000423 delete log_;
424}
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000425
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000426
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000427void Logger::IssueCodeAddedEvent(Code* code,
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000428 Script* script,
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000429 const char* name,
430 size_t name_len) {
431 JitCodeEvent event;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000432 memset(&event, 0, sizeof(event));
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000433 event.type = JitCodeEvent::CODE_ADDED;
434 event.code_start = code->instruction_start();
435 event.code_len = code->instruction_size();
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000436 Handle<Script> script_handle =
437 script != NULL ? Handle<Script>(script) : Handle<Script>();
danno@chromium.orgf95d4b92013-06-13 14:40:17 +0000438 event.script = ToApiHandle<v8::Script>(script_handle);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000439 event.name.str = name;
440 event.name.len = name_len;
441
442 code_event_handler_(&event);
443}
444
445
446void Logger::IssueCodeMovedEvent(Address from, Address to) {
447 Code* from_code = Code::cast(HeapObject::FromAddress(from));
448
449 JitCodeEvent event;
450 event.type = JitCodeEvent::CODE_MOVED;
451 event.code_start = from_code->instruction_start();
452 event.code_len = from_code->instruction_size();
453
454 // Calculate the header size.
455 const size_t header_size =
456 from_code->instruction_start() - reinterpret_cast<byte*>(from_code);
457
458 // Calculate the new start address of the instructions.
459 event.new_code_start =
460 reinterpret_cast<byte*>(HeapObject::FromAddress(to)) + header_size;
461
462 code_event_handler_(&event);
463}
464
465
466void Logger::IssueCodeRemovedEvent(Address from) {
467 Code* from_code = Code::cast(HeapObject::FromAddress(from));
468
469 JitCodeEvent event;
470 event.type = JitCodeEvent::CODE_REMOVED;
471 event.code_start = from_code->instruction_start();
472 event.code_len = from_code->instruction_size();
473
474 code_event_handler_(&event);
475}
476
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000477void Logger::IssueAddCodeLinePosInfoEvent(
478 void* jit_handler_data,
479 int pc_offset,
480 int position,
481 JitCodeEvent::PositionType position_type) {
482 JitCodeEvent event;
483 memset(&event, 0, sizeof(event));
484 event.type = JitCodeEvent::CODE_ADD_LINE_POS_INFO;
485 event.user_data = jit_handler_data;
486 event.line_info.offset = pc_offset;
487 event.line_info.pos = position;
488 event.line_info.position_type = position_type;
489
490 code_event_handler_(&event);
491}
492
493void* Logger::IssueStartCodePosInfoEvent() {
494 JitCodeEvent event;
495 memset(&event, 0, sizeof(event));
496 event.type = JitCodeEvent::CODE_START_LINE_INFO_RECORDING;
497
498 code_event_handler_(&event);
499 return event.user_data;
500}
501
502void Logger::IssueEndCodePosInfoEvent(Code* code, void* jit_handler_data) {
503 JitCodeEvent event;
504 memset(&event, 0, sizeof(event));
505 event.type = JitCodeEvent::CODE_END_LINE_INFO_RECORDING;
506 event.code_start = code->instruction_start();
507 event.user_data = jit_handler_data;
508
509 code_event_handler_(&event);
510}
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000511
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000512#define DECLARE_EVENT(ignore1, name) name,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000513static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000514 LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000515};
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000516#undef DECLARE_EVENT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000517
ager@chromium.org9085a012009-05-11 19:22:57 +0000518
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000519void Logger::ProfilerBeginEvent() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000520 if (!log_->IsEnabled()) return;
521 LogMessageBuilder msg(this);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000522 msg.Append("profiler,\"begin\",%d\n", kSamplingIntervalMs);
523 msg.WriteToLogFile();
524}
525
ager@chromium.org381abbb2009-02-25 13:23:22 +0000526
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000527void Logger::StringEvent(const char* name, const char* value) {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000528 if (FLAG_log) UncheckedStringEvent(name, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000529}
530
531
ager@chromium.org6f10e412009-02-13 10:11:16 +0000532void Logger::UncheckedStringEvent(const char* name, const char* value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000533 if (!log_->IsEnabled()) return;
534 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000535 msg.Append("%s,\"%s\"\n", name, value);
536 msg.WriteToLogFile();
ager@chromium.org6f10e412009-02-13 10:11:16 +0000537}
ager@chromium.org6f10e412009-02-13 10:11:16 +0000538
539
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000540void Logger::IntEvent(const char* name, int value) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000541 if (FLAG_log) UncheckedIntEvent(name, value);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000542}
543
544
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000545void Logger::IntPtrTEvent(const char* name, intptr_t value) {
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000546 if (FLAG_log) UncheckedIntPtrTEvent(name, value);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000547}
548
549
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000550void Logger::UncheckedIntEvent(const char* name, int value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000551 if (!log_->IsEnabled()) return;
552 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000553 msg.Append("%s,%d\n", name, value);
554 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000555}
556
557
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000558void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000559 if (!log_->IsEnabled()) return;
560 LogMessageBuilder msg(this);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000561 msg.Append("%s,%" V8_PTR_PREFIX "d\n", name, value);
562 msg.WriteToLogFile();
563}
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000564
565
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000566void Logger::HandleEvent(const char* name, Object** location) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000567 if (!log_->IsEnabled() || !FLAG_log_handles) return;
568 LogMessageBuilder msg(this);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000569 msg.Append("%s,0x%" V8PRIxPTR "\n", name, location);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000570 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000571}
572
573
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000574// ApiEvent is private so all the calls come from the Logger class. It is the
ager@chromium.org9085a012009-05-11 19:22:57 +0000575// caller's responsibility to ensure that log is enabled and that
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000576// FLAG_log_api is true.
577void Logger::ApiEvent(const char* format, ...) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000578 ASSERT(log_->IsEnabled() && FLAG_log_api);
579 LogMessageBuilder msg(this);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580 va_list ap;
581 va_start(ap, format);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000582 msg.AppendVA(format, ap);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000583 va_end(ap);
584 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000585}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000586
587
588void Logger::ApiNamedSecurityCheck(Object* key) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000589 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000590 if (key->IsString()) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000591 SmartArrayPointer<char> str =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000592 String::cast(key)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
593 ApiEvent("api,check-security,\"%s\"\n", *str);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000594 } else if (key->IsSymbol()) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000595 Symbol* symbol = Symbol::cast(key);
596 if (symbol->name()->IsUndefined()) {
597 ApiEvent("api,check-security,symbol(hash %x)\n",
598 Symbol::cast(key)->Hash());
599 } else {
600 SmartArrayPointer<char> str = String::cast(symbol->name())->ToCString(
601 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
602 ApiEvent("api,check-security,symbol(\"%s\" hash %x)\n",
603 *str,
604 Symbol::cast(key)->Hash());
605 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000606 } else if (key->IsUndefined()) {
607 ApiEvent("api,check-security,undefined\n");
608 } else {
609 ApiEvent("api,check-security,['no-name']\n");
610 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000611}
612
613
614void Logger::SharedLibraryEvent(const char* library_path,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000615 uintptr_t start,
616 uintptr_t end) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000617 if (!log_->IsEnabled() || !FLAG_prof) return;
618 LogMessageBuilder msg(this);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000619 msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
620 library_path,
621 start,
622 end);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000623 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000624}
625
626
627void Logger::SharedLibraryEvent(const wchar_t* library_path,
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000628 uintptr_t start,
629 uintptr_t end) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000630 if (!log_->IsEnabled() || !FLAG_prof) return;
631 LogMessageBuilder msg(this);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000632 msg.Append("shared-library,\"%ls\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
633 library_path,
634 start,
635 end);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000636 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000637}
638
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000639
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000640void Logger::TimerEvent(StartEnd se, const char* name) {
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000641 if (!log_->IsEnabled()) return;
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +0000642 ASSERT(FLAG_log_internal_timer_events);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000643 LogMessageBuilder msg(this);
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000644 int since_epoch = static_cast<int>(OS::Ticks() - epoch_);
645 const char* format = (se == START) ? "timer-event-start,\"%s\",%ld\n"
646 : "timer-event-end,\"%s\",%ld\n";
647 msg.Append(format, name, since_epoch);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000648 msg.WriteToLogFile();
649}
650
651
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000652void Logger::EnterExternal(Isolate* isolate) {
653 LOG(isolate, TimerEvent(START, TimerEventScope::v8_external));
654 ASSERT(isolate->current_vm_state() == JS);
655 isolate->set_current_vm_state(EXTERNAL);
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000656}
657
658
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000659void Logger::LeaveExternal(Isolate* isolate) {
660 LOG(isolate, TimerEvent(END, TimerEventScope::v8_external));
661 ASSERT(isolate->current_vm_state() == EXTERNAL);
662 isolate->set_current_vm_state(JS);
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000663}
664
665
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000666void Logger::TimerEventScope::LogTimerEvent(StartEnd se) {
667 LOG(isolate_, TimerEvent(se, name_));
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000668}
669
670
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000671const char* Logger::TimerEventScope::v8_recompile_synchronous =
672 "V8.RecompileSynchronous";
673const char* Logger::TimerEventScope::v8_recompile_parallel =
674 "V8.RecompileParallel";
675const char* Logger::TimerEventScope::v8_compile_full_code =
676 "V8.CompileFullCode";
677const char* Logger::TimerEventScope::v8_execute = "V8.Execute";
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000678const char* Logger::TimerEventScope::v8_external = "V8.External";
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000679
680
ager@chromium.org236ad962008-09-25 09:45:57 +0000681void Logger::LogRegExpSource(Handle<JSRegExp> regexp) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000682 // Prints "/" + re.source + "/" +
683 // (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000684 LogMessageBuilder msg(this);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000685
686 Handle<Object> source = GetProperty(regexp, "source");
687 if (!source->IsString()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000688 msg.Append("no source");
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000689 return;
690 }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000691
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000692 switch (regexp->TypeTag()) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000693 case JSRegExp::ATOM:
ager@chromium.org381abbb2009-02-25 13:23:22 +0000694 msg.Append('a');
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000695 break;
696 default:
697 break;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000698 }
ager@chromium.org381abbb2009-02-25 13:23:22 +0000699 msg.Append('/');
700 msg.AppendDetailed(*Handle<String>::cast(source), false);
701 msg.Append('/');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000702
703 // global flag
704 Handle<Object> global = GetProperty(regexp, "global");
705 if (global->IsTrue()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000706 msg.Append('g');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000707 }
708 // ignorecase flag
709 Handle<Object> ignorecase = GetProperty(regexp, "ignoreCase");
710 if (ignorecase->IsTrue()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000711 msg.Append('i');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000712 }
713 // multiline flag
714 Handle<Object> multiline = GetProperty(regexp, "multiline");
715 if (multiline->IsTrue()) {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000716 msg.Append('m');
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000717 }
ager@chromium.org381abbb2009-02-25 13:23:22 +0000718
719 msg.WriteToLogFile();
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000720}
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000721
722
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000723void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000724 if (!log_->IsEnabled() || !FLAG_log_regexp) return;
725 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000726 msg.Append("regexp-compile,");
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000727 LogRegExpSource(regexp);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000728 msg.Append(in_cache ? ",hit\n" : ",miss\n");
729 msg.WriteToLogFile();
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000730}
731
732
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000733void Logger::LogRuntime(Vector<const char> format,
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000734 JSArray* args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000735 if (!log_->IsEnabled() || !FLAG_log_runtime) return;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000736 HandleScope scope(isolate_);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000737 LogMessageBuilder msg(this);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000738 for (int i = 0; i < format.length(); i++) {
739 char c = format[i];
740 if (c == '%' && i <= format.length() - 2) {
741 i++;
742 ASSERT('0' <= format[i] && format[i] <= '9');
lrn@chromium.org303ada72010-10-27 09:33:13 +0000743 MaybeObject* maybe = args->GetElement(format[i] - '0');
744 Object* obj;
745 if (!maybe->ToObject(&obj)) {
746 msg.Append("<exception>");
747 continue;
748 }
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000749 i++;
750 switch (format[i]) {
751 case 's':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000752 msg.AppendDetailed(String::cast(obj), false);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000753 break;
754 case 'S':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000755 msg.AppendDetailed(String::cast(obj), true);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000756 break;
757 case 'r':
758 Logger::LogRegExpSource(Handle<JSRegExp>(JSRegExp::cast(obj)));
759 break;
760 case 'x':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000761 msg.Append("0x%x", Smi::cast(obj)->value());
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000762 break;
763 case 'i':
ager@chromium.org381abbb2009-02-25 13:23:22 +0000764 msg.Append("%i", Smi::cast(obj)->value());
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000765 break;
766 default:
767 UNREACHABLE();
768 }
769 } else {
ager@chromium.org381abbb2009-02-25 13:23:22 +0000770 msg.Append(c);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000771 }
772 }
ager@chromium.org381abbb2009-02-25 13:23:22 +0000773 msg.Append('\n');
774 msg.WriteToLogFile();
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000775}
776
777
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000778void Logger::ApiIndexedSecurityCheck(uint32_t index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000779 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000780 ApiEvent("api,check-security,%u\n", index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000781}
782
783
784void Logger::ApiNamedPropertyAccess(const char* tag,
785 JSObject* holder,
786 Object* name) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000787 ASSERT(name->IsName());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000788 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000789 String* class_name_obj = holder->class_name();
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000790 SmartArrayPointer<char> class_name =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000791 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000792 if (name->IsString()) {
793 SmartArrayPointer<char> property_name =
794 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
795 ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
796 } else {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000797 Symbol* symbol = Symbol::cast(name);
798 uint32_t hash = symbol->Hash();
799 if (symbol->name()->IsUndefined()) {
800 ApiEvent("api,%s,\"%s\",symbol(hash %x)\n", tag, *class_name, hash);
801 } else {
802 SmartArrayPointer<char> str = String::cast(symbol->name())->ToCString(
803 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
804 ApiEvent("api,%s,\"%s\",symbol(\"%s\" hash %x)\n",
805 tag, *class_name, *str, hash);
806 }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000807 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000808}
809
810void Logger::ApiIndexedPropertyAccess(const char* tag,
811 JSObject* holder,
812 uint32_t index) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000813 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000814 String* class_name_obj = holder->class_name();
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000815 SmartArrayPointer<char> class_name =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000816 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000817 ApiEvent("api,%s,\"%s\",%u\n", tag, *class_name, index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000818}
819
820void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000821 if (!log_->IsEnabled() || !FLAG_log_api) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000822 String* class_name_obj = object->class_name();
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000823 SmartArrayPointer<char> class_name =
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000824 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000825 ApiEvent("api,%s,\"%s\"\n", tag, *class_name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000826}
827
828
829void Logger::ApiEntryCall(const char* name) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000830 if (!log_->IsEnabled() || !FLAG_log_api) return;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000831 ApiEvent("api,%s\n", name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832}
833
834
835void Logger::NewEvent(const char* name, void* object, size_t size) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000836 if (!log_->IsEnabled() || !FLAG_log) return;
837 LogMessageBuilder msg(this);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000838 msg.Append("new,%s,0x%" V8PRIxPTR ",%u\n", name, object,
ager@chromium.org381abbb2009-02-25 13:23:22 +0000839 static_cast<unsigned int>(size));
840 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000841}
842
843
844void Logger::DeleteEvent(const char* name, void* object) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000845 if (!log_->IsEnabled() || !FLAG_log) return;
846 LogMessageBuilder msg(this);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +0000847 msg.Append("delete,%s,0x%" V8PRIxPTR "\n", name, object);
ager@chromium.org381abbb2009-02-25 13:23:22 +0000848 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000849}
850
851
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000852void Logger::NewEventStatic(const char* name, void* object, size_t size) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000853 Isolate::Current()->logger()->NewEvent(name, object, size);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000854}
855
856
857void Logger::DeleteEventStatic(const char* name, void* object) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000858 Isolate::Current()->logger()->DeleteEvent(name, object);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000859}
860
ulan@chromium.org750145a2013-03-07 15:14:13 +0000861void Logger::CallbackEventInternal(const char* prefix, Name* name,
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000862 Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000863 if (!log_->IsEnabled() || !FLAG_log_code) return;
864 LogMessageBuilder msg(this);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000865 msg.Append("%s,%s,-2,",
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000866 kLogEventsNames[CODE_CREATION_EVENT],
867 kLogEventsNames[CALLBACK_TAG]);
ager@chromium.org01beca72009-11-24 14:29:16 +0000868 msg.AppendAddress(entry_point);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000869 if (name->IsString()) {
870 SmartArrayPointer<char> str =
871 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
872 msg.Append(",1,\"%s%s\"", prefix, *str);
873 } else {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000874 Symbol* symbol = Symbol::cast(name);
875 if (symbol->name()->IsUndefined()) {
876 msg.Append(",1,symbol(hash %x)", prefix, symbol->Hash());
877 } else {
878 SmartArrayPointer<char> str = String::cast(symbol->name())->ToCString(
879 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
880 msg.Append(",1,symbol(\"%s\" hash %x)", prefix, *str, symbol->Hash());
881 }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000882 }
ager@chromium.org01beca72009-11-24 14:29:16 +0000883 msg.Append('\n');
884 msg.WriteToLogFile();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000885}
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000886
887
ulan@chromium.org750145a2013-03-07 15:14:13 +0000888void Logger::CallbackEvent(Name* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000889 if (!log_->IsEnabled() || !FLAG_log_code) return;
ulan@chromium.org750145a2013-03-07 15:14:13 +0000890 CallbackEventInternal("", name, entry_point);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000891}
892
893
ulan@chromium.org750145a2013-03-07 15:14:13 +0000894void Logger::GetterCallbackEvent(Name* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000895 if (!log_->IsEnabled() || !FLAG_log_code) return;
ulan@chromium.org750145a2013-03-07 15:14:13 +0000896 CallbackEventInternal("get ", name, entry_point);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000897}
898
899
ulan@chromium.org750145a2013-03-07 15:14:13 +0000900void Logger::SetterCallbackEvent(Name* name, Address entry_point) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000901 if (!log_->IsEnabled() || !FLAG_log_code) return;
ulan@chromium.org750145a2013-03-07 15:14:13 +0000902 CallbackEventInternal("set ", name, entry_point);
ager@chromium.org01beca72009-11-24 14:29:16 +0000903}
904
905
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000906void Logger::AppendName(Name* name) {
907 if (name->IsString()) {
908 name_buffer_->AppendString(String::cast(name));
909 } else {
910 Symbol* symbol = Symbol::cast(name);
911 name_buffer_->AppendBytes("symbol(");
912 if (!symbol->name()->IsUndefined()) {
913 name_buffer_->AppendBytes("\"");
914 name_buffer_->AppendString(String::cast(symbol->name()));
915 name_buffer_->AppendBytes("\" ");
916 }
917 name_buffer_->AppendBytes("hash ");
918 name_buffer_->AppendHex(symbol->Hash());
919 name_buffer_->AppendByte(')');
920 }
921}
922
923
924void Logger::InitNameBuffer(LogEventsAndTags tag) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000925 name_buffer_->Reset();
926 name_buffer_->AppendBytes(kLogEventsNames[tag]);
927 name_buffer_->AppendByte(':');
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000928}
929
930
931void Logger::LogRecordedBuffer(Code* code, SharedFunctionInfo* shared) {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000932 if (code_event_handler_ != NULL) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000933 Script* script = shared && shared->script()->IsScript() ?
934 Script::cast(shared->script()) : NULL;
935 IssueCodeAddedEvent(code,
936 script,
937 name_buffer_->get(),
938 name_buffer_->size());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000939 }
940 if (!log_->IsEnabled()) return;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000941 if (FLAG_ll_prof) {
942 LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
943 }
944 if (Serializer::enabled()) {
945 RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
946 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000947}
948
949
950void Logger::AppendCodeCreateHeader(LogMessageBuilder* msg,
951 LogEventsAndTags tag,
952 Code* code) {
953 ASSERT(msg);
954 msg->Append("%s,%s,%d,",
955 kLogEventsNames[CODE_CREATION_EVENT],
956 kLogEventsNames[tag],
957 code->kind());
958 msg->AppendAddress(code->address());
959 msg->Append(",%d,", code->ExecutableSize());
960}
961
962
963void Logger::AppendSymbolName(LogMessageBuilder* msg,
964 Symbol* symbol) {
965 ASSERT(symbol);
966 msg->Append("symbol(");
967 if (!symbol->name()->IsUndefined()) {
968 msg->Append("\"");
969 msg->AppendDetailed(String::cast(symbol->name()), false);
970 msg->Append("\" ");
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000971 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000972 msg->Append("hash %x)", symbol->Hash());
973}
974
975
976void Logger::CodeCreateEvent(LogEventsAndTags tag,
977 Code* code,
978 const char* comment) {
979 if (!is_logging_code_events()) return;
980 if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
981 InitNameBuffer(tag);
982 name_buffer_->AppendBytes(comment);
983 LogRecordedBuffer(code, NULL);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000984 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000985
986 if (!FLAG_log_code || !log_->IsEnabled()) return;
987 LogMessageBuilder msg(this);
988 AppendCodeCreateHeader(&msg, tag, code);
989 msg.AppendDoubleQuotedString(comment);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000990 msg.Append('\n');
991 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000992}
993
994
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000995void Logger::CodeCreateEvent(LogEventsAndTags tag,
996 Code* code,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000997 Name* name) {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000998 if (!is_logging_code_events()) return;
999 if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001000 InitNameBuffer(tag);
1001 AppendName(name);
1002 LogRecordedBuffer(code, NULL);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001003 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001004
1005 if (!FLAG_log_code || !log_->IsEnabled()) return;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001006 LogMessageBuilder msg(this);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001007 AppendCodeCreateHeader(&msg, tag, code);
ulan@chromium.org750145a2013-03-07 15:14:13 +00001008 if (name->IsString()) {
1009 msg.Append('"');
1010 msg.AppendDetailed(String::cast(name), false);
1011 msg.Append('"');
1012 } else {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001013 AppendSymbolName(&msg, Symbol::cast(name));
ulan@chromium.org750145a2013-03-07 15:14:13 +00001014 }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001015 msg.Append('\n');
1016 msg.WriteToLogFile();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001017}
1018
1019
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001020// ComputeMarker must only be used when SharedFunctionInfo is known.
1021static const char* ComputeMarker(Code* code) {
1022 switch (code->kind()) {
1023 case Code::FUNCTION: return code->optimizable() ? "~" : "";
1024 case Code::OPTIMIZED_FUNCTION: return "*";
1025 default: return "";
1026 }
1027}
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001028
1029
1030void Logger::CodeCreateEvent(LogEventsAndTags tag,
1031 Code* code,
1032 SharedFunctionInfo* shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001033 CompilationInfo* info,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001034 Name* name) {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001035 if (!is_logging_code_events()) return;
1036 if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001037 InitNameBuffer(tag);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001038 name_buffer_->AppendBytes(ComputeMarker(code));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001039 AppendName(name);
1040 LogRecordedBuffer(code, shared);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001041 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001042
1043 if (!FLAG_log_code || !log_->IsEnabled()) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001044 if (code == Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001045 Builtins::kLazyCompile))
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001046 return;
1047
1048 LogMessageBuilder msg(this);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001049 AppendCodeCreateHeader(&msg, tag, code);
ulan@chromium.org750145a2013-03-07 15:14:13 +00001050 if (name->IsString()) {
1051 SmartArrayPointer<char> str =
1052 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1053 msg.Append("\"%s\"", *str);
1054 } else {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001055 AppendSymbolName(&msg, Symbol::cast(name));
ulan@chromium.org750145a2013-03-07 15:14:13 +00001056 }
1057 msg.Append(',');
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001058 msg.AppendAddress(shared->address());
1059 msg.Append(",%s", ComputeMarker(code));
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001060 msg.Append('\n');
1061 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001062}
1063
1064
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001065// Although, it is possible to extract source and line from
1066// the SharedFunctionInfo object, we left it to caller
1067// to leave logging functions free from heap allocations.
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001068void Logger::CodeCreateEvent(LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001069 Code* code,
1070 SharedFunctionInfo* shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001071 CompilationInfo* info,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001072 Name* source, int line) {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001073 if (!is_logging_code_events()) return;
1074 if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001075 InitNameBuffer(tag);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001076 name_buffer_->AppendBytes(ComputeMarker(code));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001077 name_buffer_->AppendString(shared->DebugName());
1078 name_buffer_->AppendByte(' ');
ulan@chromium.org750145a2013-03-07 15:14:13 +00001079 if (source->IsString()) {
1080 name_buffer_->AppendString(String::cast(source));
1081 } else {
1082 name_buffer_->AppendBytes("symbol(hash ");
1083 name_buffer_->AppendHex(Name::cast(source)->Hash());
1084 name_buffer_->AppendByte(')');
1085 }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001086 name_buffer_->AppendByte(':');
1087 name_buffer_->AppendInt(line);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001088 LogRecordedBuffer(code, shared);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001089 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001090
1091 if (!FLAG_log_code || !log_->IsEnabled()) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001092 LogMessageBuilder msg(this);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001093 AppendCodeCreateHeader(&msg, tag, code);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001094 SmartArrayPointer<char> name =
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001095 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001096 msg.Append("\"%s ", *name);
ulan@chromium.org750145a2013-03-07 15:14:13 +00001097 if (source->IsString()) {
1098 SmartArrayPointer<char> sourcestr =
1099 String::cast(source)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1100 msg.Append("%s", *sourcestr);
1101 } else {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001102 AppendSymbolName(&msg, Symbol::cast(source));
ulan@chromium.org750145a2013-03-07 15:14:13 +00001103 }
1104 msg.Append(":%d\",", line);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001105 msg.AppendAddress(shared->address());
1106 msg.Append(",%s", ComputeMarker(code));
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001107 msg.Append('\n');
1108 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001109}
1110
1111
1112void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001113 if (!is_logging_code_events()) return;
1114 if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001115 InitNameBuffer(tag);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001116 name_buffer_->AppendInt(args_count);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001117 LogRecordedBuffer(code, NULL);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001118 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001119
1120 if (!FLAG_log_code || !log_->IsEnabled()) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001121 LogMessageBuilder msg(this);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001122 AppendCodeCreateHeader(&msg, tag, code);
1123 msg.Append("\"args_count: %d\"", args_count);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001124 msg.Append('\n');
1125 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001126}
1127
1128
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001129void Logger::CodeMovingGCEvent() {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001130 if (!log_->IsEnabled() || !FLAG_ll_prof) return;
1131 LowLevelLogWriteBytes(&kCodeMovingGCTag, sizeof(kCodeMovingGCTag));
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001132 OS::SignalCodeMovingGC();
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001133}
1134
1135
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001136void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001137 if (!is_logging_code_events()) return;
1138 if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001139 InitNameBuffer(REG_EXP_TAG);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001140 name_buffer_->AppendString(source);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001141 LogRecordedBuffer(code, NULL);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001142 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001143
1144 if (!FLAG_log_code || !log_->IsEnabled()) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001145 LogMessageBuilder msg(this);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001146 AppendCodeCreateHeader(&msg, REG_EXP_TAG, code);
1147 msg.Append('"');
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001148 msg.AppendDetailed(source, false);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001149 msg.Append('"');
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001150 msg.Append('\n');
1151 msg.WriteToLogFile();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001152}
1153
1154
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001155void Logger::CodeMoveEvent(Address from, Address to) {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001156 if (code_event_handler_ != NULL) IssueCodeMovedEvent(from, to);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001157 if (!log_->IsEnabled()) return;
1158 if (FLAG_ll_prof) LowLevelCodeMoveEvent(from, to);
1159 if (Serializer::enabled() && address_to_name_map_ != NULL) {
1160 address_to_name_map_->Move(from, to);
1161 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001162 MoveEventInternal(CODE_MOVE_EVENT, from, to);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001163}
1164
1165
1166void Logger::CodeDeleteEvent(Address from) {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001167 if (code_event_handler_ != NULL) IssueCodeRemovedEvent(from);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001168 if (!log_->IsEnabled()) return;
1169 if (FLAG_ll_prof) LowLevelCodeDeleteEvent(from);
1170 if (Serializer::enabled() && address_to_name_map_ != NULL) {
1171 address_to_name_map_->Remove(from);
1172 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001173 DeleteEventInternal(CODE_DELETE_EVENT, from);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001174}
1175
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001176void Logger::CodeLinePosInfoAddPositionEvent(void* jit_handler_data,
1177 int pc_offset,
1178 int position) {
1179 if (code_event_handler_ != NULL) {
1180 IssueAddCodeLinePosInfoEvent(jit_handler_data,
1181 pc_offset,
1182 position,
1183 JitCodeEvent::POSITION);
1184 }
1185}
1186
1187void Logger::CodeLinePosInfoAddStatementPositionEvent(void* jit_handler_data,
1188 int pc_offset,
1189 int position) {
1190 if (code_event_handler_ != NULL) {
1191 IssueAddCodeLinePosInfoEvent(jit_handler_data,
1192 pc_offset,
1193 position,
1194 JitCodeEvent::STATEMENT_POSITION);
1195 }
1196}
1197
1198void Logger::CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder) {
1199 if (code_event_handler_ != NULL) {
1200 pos_recorder->AttachJITHandlerData(IssueStartCodePosInfoEvent());
1201 }
1202}
1203
1204void Logger::CodeEndLinePosInfoRecordEvent(Code* code,
1205 void* jit_handler_data) {
1206 if (code_event_handler_ != NULL) {
1207 IssueEndCodePosInfoEvent(code, jit_handler_data);
1208 }
1209}
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001210
1211void Logger::SnapshotPositionEvent(Address addr, int pos) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001212 if (!log_->IsEnabled()) return;
1213 if (FLAG_ll_prof) LowLevelSnapshotPositionEvent(addr, pos);
1214 if (Serializer::enabled() && address_to_name_map_ != NULL) {
1215 const char* code_name = address_to_name_map_->Lookup(addr);
1216 if (code_name == NULL) return; // Not a code object.
1217 LogMessageBuilder msg(this);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001218 msg.Append("%s,%d,", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
1219 msg.AppendDoubleQuotedString(code_name);
1220 msg.Append("\n");
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001221 msg.WriteToLogFile();
1222 }
1223 if (!FLAG_log_snapshot_positions) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001224 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001225 msg.Append("%s,", kLogEventsNames[SNAPSHOT_POSITION_EVENT]);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001226 msg.AppendAddress(addr);
1227 msg.Append(",%d", pos);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001228 msg.Append('\n');
1229 msg.WriteToLogFile();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001230}
1231
1232
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001233void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001234 MoveEventInternal(SHARED_FUNC_MOVE_EVENT, from, to);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001235}
1236
1237
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001238void Logger::MoveEventInternal(LogEventsAndTags event,
1239 Address from,
1240 Address to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001241 if (!log_->IsEnabled() || !FLAG_log_code) return;
1242 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001243 msg.Append("%s,", kLogEventsNames[event]);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001244 msg.AppendAddress(from);
1245 msg.Append(',');
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001246 msg.AppendAddress(to);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001247 msg.Append('\n');
ager@chromium.org381abbb2009-02-25 13:23:22 +00001248 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001249}
1250
1251
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001252void Logger::DeleteEventInternal(LogEventsAndTags event, Address from) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001253 if (!log_->IsEnabled() || !FLAG_log_code) return;
1254 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001255 msg.Append("%s,", kLogEventsNames[event]);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001256 msg.AppendAddress(from);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001257 msg.Append('\n');
ager@chromium.org381abbb2009-02-25 13:23:22 +00001258 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001259}
1260
1261
1262void Logger::ResourceEvent(const char* name, const char* tag) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001263 if (!log_->IsEnabled() || !FLAG_log) return;
1264 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001265 msg.Append("%s,%s,", name, tag);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001266
1267 uint32_t sec, usec;
1268 if (OS::GetUserTime(&sec, &usec) != -1) {
ager@chromium.org381abbb2009-02-25 13:23:22 +00001269 msg.Append("%d,%d,", sec, usec);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001270 }
ager@chromium.org381abbb2009-02-25 13:23:22 +00001271 msg.Append("%.0f", OS::TimeCurrentMillis());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001272
ager@chromium.org381abbb2009-02-25 13:23:22 +00001273 msg.Append('\n');
1274 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001275}
1276
1277
ulan@chromium.org750145a2013-03-07 15:14:13 +00001278void Logger::SuspectReadEvent(Name* name, Object* obj) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001279 if (!log_->IsEnabled() || !FLAG_log_suspect) return;
1280 LogMessageBuilder msg(this);
ager@chromium.org8bb60582008-12-11 12:02:20 +00001281 String* class_name = obj->IsJSObject()
1282 ? JSObject::cast(obj)->class_name()
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001283 : isolate_->heap()->empty_string();
ager@chromium.org381abbb2009-02-25 13:23:22 +00001284 msg.Append("suspect-read,");
1285 msg.Append(class_name);
1286 msg.Append(',');
ulan@chromium.org750145a2013-03-07 15:14:13 +00001287 if (name->IsString()) {
1288 msg.Append('"');
1289 msg.Append(String::cast(name));
1290 msg.Append('"');
1291 } else {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001292 AppendSymbolName(&msg, Symbol::cast(name));
ulan@chromium.org750145a2013-03-07 15:14:13 +00001293 }
ager@chromium.org381abbb2009-02-25 13:23:22 +00001294 msg.Append('\n');
1295 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001296}
1297
1298
1299void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001300 if (!log_->IsEnabled() || !FLAG_log_gc) return;
1301 LogMessageBuilder msg(this);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001302 // Using non-relative system time in order to be able to synchronize with
1303 // external memory profiling events (e.g. DOM memory size).
1304 msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f\n",
1305 space, kind, OS::TimeCurrentMillis());
1306 msg.WriteToLogFile();
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001307}
1308
1309
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001310void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001311 if (!log_->IsEnabled() || !FLAG_log_gc) return;
1312 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001313 msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind);
1314 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001315}
1316
1317
1318void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001319 if (!log_->IsEnabled() || !FLAG_log_gc) return;
1320 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001321 msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes);
1322 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001323}
1324
1325
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001326void Logger::DebugTag(const char* call_site_tag) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001327 if (!log_->IsEnabled() || !FLAG_log) return;
1328 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001329 msg.Append("debug-tag,%s\n", call_site_tag);
1330 msg.WriteToLogFile();
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001331}
1332
1333
1334void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001335 if (!log_->IsEnabled() || !FLAG_log) return;
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001336 StringBuilder s(parameter.length() + 1);
1337 for (int i = 0; i < parameter.length(); ++i) {
1338 s.AddCharacter(static_cast<char>(parameter[i]));
1339 }
1340 char* parameter_string = s.Finalize();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001341 LogMessageBuilder msg(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001342 msg.Append("debug-queue-event,%s,%15.3f,%s\n",
1343 event_type,
1344 OS::TimeCurrentMillis(),
1345 parameter_string);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001346 DeleteArray(parameter_string);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001347 msg.WriteToLogFile();
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00001348}
1349
1350
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001351void Logger::TickEvent(TickSample* sample, bool overflow) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001352 if (!log_->IsEnabled() || !FLAG_prof) return;
1353 LogMessageBuilder msg(this);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001354 msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
1355 msg.AppendAddress(sample->pc);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001356 msg.Append(',');
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001357 msg.AppendAddress(sample->sp);
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00001358 msg.Append(",%ld", static_cast<int>(OS::Ticks() - epoch_));
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001359 if (sample->has_external_callback) {
1360 msg.Append(",1,");
1361 msg.AppendAddress(sample->external_callback);
1362 } else {
1363 msg.Append(",0,");
1364 msg.AppendAddress(sample->tos);
1365 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001366 msg.Append(",%d", static_cast<int>(sample->state));
ager@chromium.org381abbb2009-02-25 13:23:22 +00001367 if (overflow) {
1368 msg.Append(",overflow");
1369 }
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001370 for (int i = 0; i < sample->frames_count; ++i) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001371 msg.Append(',');
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001372 msg.AppendAddress(sample->stack[i]);
ager@chromium.org381abbb2009-02-25 13:23:22 +00001373 }
1374 msg.Append('\n');
1375 msg.WriteToLogFile();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001376}
iposva@chromium.org245aa852009-02-10 00:49:54 +00001377
1378
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001379bool Logger::IsProfilerPaused() {
1380 return profiler_ == NULL || profiler_->paused();
iposva@chromium.org245aa852009-02-10 00:49:54 +00001381}
1382
1383
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001384void Logger::PauseProfiler() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001385 if (!log_->IsEnabled()) return;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001386 if (profiler_ != NULL) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001387 // It is OK to have negative nesting.
1388 if (--cpu_profiler_nesting_ == 0) {
1389 profiler_->pause();
1390 if (FLAG_prof_lazy) {
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +00001391 ticker_->Stop();
ager@chromium.org5c838252010-02-19 08:53:10 +00001392 FLAG_log_code = false;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001393 LOG(ISOLATE, UncheckedStringEvent("profiler", "pause"));
ager@chromium.org5c838252010-02-19 08:53:10 +00001394 }
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001395 --logging_nesting_;
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00001396 }
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001397 }
iposva@chromium.org245aa852009-02-10 00:49:54 +00001398}
1399
1400
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001401void Logger::ResumeProfiler() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001402 if (!log_->IsEnabled()) return;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001403 if (profiler_ != NULL) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001404 if (cpu_profiler_nesting_++ == 0) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001405 ++logging_nesting_;
ager@chromium.org5c838252010-02-19 08:53:10 +00001406 if (FLAG_prof_lazy) {
1407 profiler_->Engage();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001408 LOG(ISOLATE, UncheckedStringEvent("profiler", "resume"));
ager@chromium.org5c838252010-02-19 08:53:10 +00001409 FLAG_log_code = true;
1410 LogCompiledFunctions();
ager@chromium.org5c838252010-02-19 08:53:10 +00001411 LogAccessorCallbacks();
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +00001412 if (!ticker_->IsActive()) ticker_->Start();
ager@chromium.org5c838252010-02-19 08:53:10 +00001413 }
1414 profiler_->resume();
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +00001415 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001416 }
iposva@chromium.org245aa852009-02-10 00:49:54 +00001417}
ager@chromium.org9085a012009-05-11 19:22:57 +00001418
1419
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001420// This function can be called when Log's mutex is acquired,
1421// either from main or Profiler's thread.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001422void Logger::LogFailure() {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001423 PauseProfiler();
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001424}
1425
1426
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001427class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor {
1428 public:
1429 EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis,
1430 Handle<Code>* code_objects,
1431 int* count)
1432 : sfis_(sfis), code_objects_(code_objects), count_(count) { }
1433
1434 virtual void EnterContext(Context* context) {}
1435 virtual void LeaveContext(Context* context) {}
1436
1437 virtual void VisitFunction(JSFunction* function) {
whesse@chromium.org7b260152011-06-20 15:33:18 +00001438 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(function->shared());
1439 Object* maybe_script = sfi->script();
1440 if (maybe_script->IsScript()
1441 && !Script::cast(maybe_script)->HasValidSource()) return;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001442 if (sfis_ != NULL) {
whesse@chromium.org7b260152011-06-20 15:33:18 +00001443 sfis_[*count_] = Handle<SharedFunctionInfo>(sfi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001444 }
1445 if (code_objects_ != NULL) {
1446 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
1447 code_objects_[*count_] = Handle<Code>(function->code());
1448 }
1449 *count_ = *count_ + 1;
1450 }
1451
1452 private:
1453 Handle<SharedFunctionInfo>* sfis_;
1454 Handle<Code>* code_objects_;
1455 int* count_;
1456};
1457
1458
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001459static int EnumerateCompiledFunctions(Heap* heap,
1460 Handle<SharedFunctionInfo>* sfis,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001461 Handle<Code>* code_objects) {
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001462 HeapIterator iterator(heap);
rossberg@chromium.org79e79022013-06-03 15:43:46 +00001463 DisallowHeapAllocation no_gc;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001464 int compiled_funcs_count = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001465
1466 // Iterate the heap to find shared function info objects and record
1467 // the unoptimized code for them.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001468 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001469 if (!obj->IsSharedFunctionInfo()) continue;
1470 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
1471 if (sfi->is_compiled()
1472 && (!sfi->script()->IsScript()
1473 || Script::cast(sfi->script())->HasValidSource())) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001474 if (sfis != NULL) {
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001475 sfis[compiled_funcs_count] = Handle<SharedFunctionInfo>(sfi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001476 }
1477 if (code_objects != NULL) {
1478 code_objects[compiled_funcs_count] = Handle<Code>(sfi->code());
1479 }
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001480 ++compiled_funcs_count;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001481 }
1482 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001483
1484 // Iterate all optimized functions in all contexts.
1485 EnumerateOptimizedFunctionsVisitor visitor(sfis,
1486 code_objects,
1487 &compiled_funcs_count);
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001488 Deoptimizer::VisitAllOptimizedFunctions(heap->isolate(), &visitor);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001489
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001490 return compiled_funcs_count;
1491}
1492
1493
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001494void Logger::LogCodeObject(Object* object) {
rossberg@chromium.org79e79022013-06-03 15:43:46 +00001495 Code* code_object = Code::cast(object);
1496 LogEventsAndTags tag = Logger::STUB_TAG;
1497 const char* description = "Unknown code from the snapshot";
1498 switch (code_object->kind()) {
1499 case Code::FUNCTION:
1500 case Code::OPTIMIZED_FUNCTION:
1501 return; // We log this later using LogCompiledFunctions.
1502 case Code::UNARY_OP_IC: // fall through
1503 case Code::BINARY_OP_IC: // fall through
1504 case Code::COMPARE_IC: // fall through
1505 case Code::COMPARE_NIL_IC: // fall through
1506 case Code::TO_BOOLEAN_IC: // fall through
1507 case Code::STUB:
1508 description =
1509 CodeStub::MajorName(CodeStub::GetMajorKey(code_object), true);
1510 if (description == NULL)
1511 description = "A stub from the snapshot";
1512 tag = Logger::STUB_TAG;
1513 break;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001514 case Code::REGEXP:
1515 description = "Regular expression code";
1516 tag = Logger::REG_EXP_TAG;
1517 break;
rossberg@chromium.org79e79022013-06-03 15:43:46 +00001518 case Code::BUILTIN:
1519 description = "A builtin from the snapshot";
1520 tag = Logger::BUILTIN_TAG;
1521 break;
1522 case Code::KEYED_LOAD_IC:
1523 description = "A keyed load IC from the snapshot";
1524 tag = Logger::KEYED_LOAD_IC_TAG;
1525 break;
1526 case Code::LOAD_IC:
1527 description = "A load IC from the snapshot";
1528 tag = Logger::LOAD_IC_TAG;
1529 break;
1530 case Code::STORE_IC:
1531 description = "A store IC from the snapshot";
1532 tag = Logger::STORE_IC_TAG;
1533 break;
1534 case Code::KEYED_STORE_IC:
1535 description = "A keyed store IC from the snapshot";
1536 tag = Logger::KEYED_STORE_IC_TAG;
1537 break;
1538 case Code::CALL_IC:
1539 description = "A call IC from the snapshot";
1540 tag = Logger::CALL_IC_TAG;
1541 break;
1542 case Code::KEYED_CALL_IC:
1543 description = "A keyed call IC from the snapshot";
1544 tag = Logger::KEYED_CALL_IC_TAG;
1545 break;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001546 case Code::NUMBER_OF_KINDS:
1547 break;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001548 }
rossberg@chromium.org79e79022013-06-03 15:43:46 +00001549 PROFILE(isolate_, CodeCreateEvent(tag, code_object, description));
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001550}
1551
1552
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001553void Logger::LogCodeInfo() {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001554 if (!log_->IsEnabled() || !FLAG_ll_prof) return;
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001555#if V8_TARGET_ARCH_IA32
1556 const char arch[] = "ia32";
1557#elif V8_TARGET_ARCH_X64
1558 const char arch[] = "x64";
1559#elif V8_TARGET_ARCH_ARM
1560 const char arch[] = "arm";
danno@chromium.orgc612e022011-11-10 11:38:15 +00001561#elif V8_TARGET_ARCH_MIPS
1562 const char arch[] = "mips";
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001563#else
1564 const char arch[] = "unknown";
1565#endif
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001566 LowLevelLogWriteBytes(arch, sizeof(arch));
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001567}
1568
1569
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001570void Logger::RegisterSnapshotCodeName(Code* code,
1571 const char* name,
1572 int name_size) {
1573 ASSERT(Serializer::enabled());
1574 if (address_to_name_map_ == NULL) {
1575 address_to_name_map_ = new NameMap;
1576 }
1577 address_to_name_map_->Insert(code->address(), name, name_size);
1578}
1579
1580
1581void Logger::LowLevelCodeCreateEvent(Code* code,
1582 const char* name,
1583 int name_size) {
1584 if (log_->ll_output_handle_ == NULL) return;
1585 LowLevelCodeCreateStruct event;
1586 event.name_size = name_size;
1587 event.code_address = code->instruction_start();
1588 ASSERT(event.code_address == code->address() + Code::kHeaderSize);
1589 event.code_size = code->instruction_size();
1590 LowLevelLogWriteStruct(event);
1591 LowLevelLogWriteBytes(name, name_size);
1592 LowLevelLogWriteBytes(
1593 reinterpret_cast<const char*>(code->instruction_start()),
1594 code->instruction_size());
1595}
1596
1597
1598void Logger::LowLevelCodeMoveEvent(Address from, Address to) {
1599 if (log_->ll_output_handle_ == NULL) return;
1600 LowLevelCodeMoveStruct event;
1601 event.from_address = from + Code::kHeaderSize;
1602 event.to_address = to + Code::kHeaderSize;
1603 LowLevelLogWriteStruct(event);
1604}
1605
1606
1607void Logger::LowLevelCodeDeleteEvent(Address from) {
1608 if (log_->ll_output_handle_ == NULL) return;
1609 LowLevelCodeDeleteStruct event;
1610 event.address = from + Code::kHeaderSize;
1611 LowLevelLogWriteStruct(event);
1612}
1613
1614
1615void Logger::LowLevelSnapshotPositionEvent(Address addr, int pos) {
1616 if (log_->ll_output_handle_ == NULL) return;
1617 LowLevelSnapshotPositionStruct event;
1618 event.address = addr + Code::kHeaderSize;
1619 event.position = pos;
1620 LowLevelLogWriteStruct(event);
1621}
1622
1623
1624void Logger::LowLevelLogWriteBytes(const char* bytes, int size) {
1625 size_t rv = fwrite(bytes, 1, size, log_->ll_output_handle_);
1626 ASSERT(static_cast<size_t>(size) == rv);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001627 USE(rv);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001628}
1629
1630
ager@chromium.org5c838252010-02-19 08:53:10 +00001631void Logger::LogCodeObjects() {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001632 Heap* heap = isolate_->heap();
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001633 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
rossberg@chromium.org994edf62012-02-06 10:12:55 +00001634 "Logger::LogCodeObjects");
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001635 HeapIterator iterator(heap);
rossberg@chromium.org79e79022013-06-03 15:43:46 +00001636 DisallowHeapAllocation no_gc;
ager@chromium.org5c838252010-02-19 08:53:10 +00001637 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1638 if (obj->IsCode()) LogCodeObject(obj);
1639 }
1640}
1641
1642
lrn@chromium.org34e60782011-09-15 07:25:40 +00001643void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
1644 Handle<Code> code) {
1645 Handle<String> func_name(shared->DebugName());
1646 if (shared->script()->IsScript()) {
1647 Handle<Script> script(Script::cast(shared->script()));
1648 if (script->name()->IsString()) {
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00001649 Handle<String> script_name(String::cast(script->name()));
lrn@chromium.org34e60782011-09-15 07:25:40 +00001650 int line_num = GetScriptLineNumber(script, shared->start_position());
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00001651 if (line_num > 0) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001652 PROFILE(isolate_,
lrn@chromium.org34e60782011-09-15 07:25:40 +00001653 CodeCreateEvent(
1654 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001655 *code, *shared, NULL,
lrn@chromium.org34e60782011-09-15 07:25:40 +00001656 *script_name, line_num + 1));
1657 } else {
1658 // Can't distinguish eval and script here, so always use Script.
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001659 PROFILE(isolate_,
lrn@chromium.org34e60782011-09-15 07:25:40 +00001660 CodeCreateEvent(
1661 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001662 *code, *shared, NULL, *script_name));
lrn@chromium.org34e60782011-09-15 07:25:40 +00001663 }
1664 } else {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001665 PROFILE(isolate_,
lrn@chromium.org34e60782011-09-15 07:25:40 +00001666 CodeCreateEvent(
1667 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001668 *code, *shared, NULL, *func_name));
lrn@chromium.org34e60782011-09-15 07:25:40 +00001669 }
1670 } else if (shared->IsApiFunction()) {
1671 // API function.
1672 FunctionTemplateInfo* fun_data = shared->get_api_func_data();
1673 Object* raw_call_data = fun_data->call_code();
1674 if (!raw_call_data->IsUndefined()) {
1675 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1676 Object* callback_obj = call_data->callback();
1677 Address entry_point = v8::ToCData<Address>(callback_obj);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001678 PROFILE(isolate_, CallbackEvent(*func_name, entry_point));
lrn@chromium.org34e60782011-09-15 07:25:40 +00001679 }
1680 } else {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001681 PROFILE(isolate_,
lrn@chromium.org34e60782011-09-15 07:25:40 +00001682 CodeCreateEvent(
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001683 Logger::LAZY_COMPILE_TAG, *code, *shared, NULL, *func_name));
lrn@chromium.org34e60782011-09-15 07:25:40 +00001684 }
1685}
1686
1687
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +00001688void Logger::LogCompiledFunctions() {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001689 Heap* heap = isolate_->heap();
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001690 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
rossberg@chromium.org994edf62012-02-06 10:12:55 +00001691 "Logger::LogCompiledFunctions");
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001692 HandleScope scope(isolate_);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001693 const int compiled_funcs_count = EnumerateCompiledFunctions(heap, NULL, NULL);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001694 ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001695 ScopedVector< Handle<Code> > code_objects(compiled_funcs_count);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001696 EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start());
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001697
1698 // During iteration, there can be heap allocation due to
1699 // GetScriptLineNumber call.
1700 for (int i = 0; i < compiled_funcs_count; ++i) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001701 if (*code_objects[i] == Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001702 Builtins::kLazyCompile))
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001703 continue;
lrn@chromium.org34e60782011-09-15 07:25:40 +00001704 LogExistingFunction(sfis[i], code_objects[i]);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001705 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001706}
1707
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001708
1709void Logger::LogAccessorCallbacks() {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001710 Heap* heap = isolate_->heap();
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001711 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
rossberg@chromium.org994edf62012-02-06 10:12:55 +00001712 "Logger::LogAccessorCallbacks");
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001713 HeapIterator iterator(heap);
rossberg@chromium.org79e79022013-06-03 15:43:46 +00001714 DisallowHeapAllocation no_gc;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001715 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001716 if (!obj->IsExecutableAccessorInfo()) continue;
1717 ExecutableAccessorInfo* ai = ExecutableAccessorInfo::cast(obj);
ulan@chromium.org750145a2013-03-07 15:14:13 +00001718 if (!ai->name()->IsName()) continue;
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001719 Address getter_entry = v8::ToCData<Address>(ai->getter());
ulan@chromium.org750145a2013-03-07 15:14:13 +00001720 Name* name = Name::cast(ai->name());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001721 if (getter_entry != 0) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001722 PROFILE(isolate_, GetterCallbackEvent(name, getter_entry));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001723 }
1724 Address setter_entry = v8::ToCData<Address>(ai->setter());
1725 if (setter_entry != 0) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001726 PROFILE(isolate_, SetterCallbackEvent(name, setter_entry));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001727 }
1728 }
1729}
1730
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001731
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001732bool Logger::SetUp(Isolate* isolate) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001733 // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
1734 if (is_initialized_) return true;
1735 is_initialized_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001736
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001737 // --ll-prof implies --log-code and --log-snapshot-positions.
1738 if (FLAG_ll_prof) {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001739 FLAG_log_snapshot_positions = true;
1740 }
1741
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001742 // --prof_lazy controls --log-code, implies --noprof_auto.
1743 if (FLAG_prof_lazy) {
1744 FLAG_log_code = false;
1745 FLAG_prof_auto = false;
1746 }
1747
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001748 log_->Initialize();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001749
whesse@chromium.org4a5224e2010-10-20 12:37:07 +00001750 if (FLAG_ll_prof) LogCodeInfo();
1751
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001752 ticker_ = new Ticker(isolate, kSamplingIntervalMs);
1753
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001754 if (Log::InitLogAtStart()) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001755 logging_nesting_ = 1;
1756 }
ager@chromium.org3e875802009-06-29 08:26:34 +00001757
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001758 if (FLAG_prof) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001759 profiler_ = new Profiler(isolate);
ager@chromium.org3e875802009-06-29 08:26:34 +00001760 if (!FLAG_prof_auto) {
iposva@chromium.org245aa852009-02-10 00:49:54 +00001761 profiler_->pause();
ager@chromium.org3e875802009-06-29 08:26:34 +00001762 } else {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001763 logging_nesting_ = 1;
ager@chromium.org3e875802009-06-29 08:26:34 +00001764 }
ager@chromium.org3811b432009-10-28 14:53:37 +00001765 if (!FLAG_prof_lazy) {
1766 profiler_->Engage();
1767 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001768 }
1769
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00001770 if (FLAG_log_internal_timer_events || FLAG_prof) epoch_ = OS::Ticks();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001771
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001772 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001773}
1774
1775
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001776void Logger::SetCodeEventHandler(uint32_t options,
1777 JitCodeEventHandler event_handler) {
1778 code_event_handler_ = event_handler;
1779
1780 if (code_event_handler_ != NULL && (options & kJitCodeEventEnumExisting)) {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001781 HandleScope scope(Isolate::Current());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001782 LogCodeObjects();
1783 LogCompiledFunctions();
1784 }
1785}
1786
1787
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001788Sampler* Logger::sampler() {
1789 return ticker_;
1790}
1791
1792
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001793FILE* Logger::TearDown() {
1794 if (!is_initialized_) return NULL;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001795 is_initialized_ = false;
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001796
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001797 // Stop the profiler before closing the file.
1798 if (profiler_ != NULL) {
1799 profiler_->Disengage();
1800 delete profiler_;
1801 profiler_ = NULL;
1802 }
1803
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001804 delete ticker_;
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001805 ticker_ = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001806
whesse@chromium.org030d38e2011-07-13 13:23:34 +00001807 return log_->Close();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001808}
1809
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001810} } // namespace v8::internal