blob: a10d9621d32a7ea721e9599fc42ec67cca33faf2 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/log.h"
6
7#include <cstdarg>
8#include <sstream>
Steve Blocka7e24c12009-10-30 11:49:00 +00009
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/bailout-reason.h"
11#include "src/base/platform/platform.h"
12#include "src/bootstrapper.h"
13#include "src/code-stubs.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014#include "src/deoptimizer.h"
15#include "src/global-handles.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016#include "src/log-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017#include "src/log-utils.h"
18#include "src/macro-assembler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019#include "src/profiler/cpu-profiler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020#include "src/runtime-profiler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021#include "src/string-stream.h"
22#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000023
24namespace v8 {
25namespace internal {
26
Steve Blocka7e24c12009-10-30 11:49:00 +000027
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028#define DECLARE_EVENT(ignore1, name) name,
29static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
30 LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)
Steve Blocka7e24c12009-10-30 11:49:00 +000031};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032#undef DECLARE_EVENT
Steve Blocka7e24c12009-10-30 11:49:00 +000033
34
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035#define CALL_LISTENERS(Call) \
36for (int i = 0; i < listeners_.length(); ++i) { \
37 listeners_[i]->Call; \
Steve Blocka7e24c12009-10-30 11:49:00 +000038}
39
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040#define PROFILER_LOG(Call) \
41 do { \
42 CpuProfiler* cpu_profiler = isolate_->cpu_profiler(); \
43 if (cpu_profiler->is_profiling()) { \
44 cpu_profiler->Call; \
45 } \
46 } while (false);
Steve Blocka7e24c12009-10-30 11:49:00 +000047
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000048static const char* ComputeMarker(SharedFunctionInfo* shared, Code* code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049 switch (code->kind()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 case Code::FUNCTION:
51 return shared->optimization_disabled() ? "" : "~";
52 case Code::OPTIMIZED_FUNCTION:
53 return "*";
54 default:
55 return "";
Steve Blocka7e24c12009-10-30 11:49:00 +000056 }
57}
58
59
Ben Murdochb8a8cc12014-11-26 15:28:44 +000060class CodeEventLogger::NameBuffer {
Ben Murdoch257744e2011-11-30 15:57:28 +000061 public:
62 NameBuffer() { Reset(); }
63
64 void Reset() {
65 utf8_pos_ = 0;
66 }
67
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068 void Init(Logger::LogEventsAndTags tag) {
69 Reset();
70 AppendBytes(kLogEventsNames[tag]);
71 AppendByte(':');
72 }
73
74 void AppendName(Name* name) {
75 if (name->IsString()) {
76 AppendString(String::cast(name));
77 } else {
78 Symbol* symbol = Symbol::cast(name);
79 AppendBytes("symbol(");
80 if (!symbol->name()->IsUndefined()) {
81 AppendBytes("\"");
82 AppendString(String::cast(symbol->name()));
83 AppendBytes("\" ");
84 }
85 AppendBytes("hash ");
86 AppendHex(symbol->Hash());
87 AppendByte(')');
88 }
89 }
90
Ben Murdoch257744e2011-11-30 15:57:28 +000091 void AppendString(String* str) {
92 if (str == NULL) return;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010093 int uc16_length = Min(str->length(), kUtf16BufferSize);
94 String::WriteToFlat(str, utf16_buffer, 0, uc16_length);
95 int previous = unibrow::Utf16::kNoPreviousCharacter;
Ben Murdoch257744e2011-11-30 15:57:28 +000096 for (int i = 0; i < uc16_length && utf8_pos_ < kUtf8BufferSize; ++i) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010097 uc16 c = utf16_buffer[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 if (c <= unibrow::Utf8::kMaxOneByteChar) {
Ben Murdoch257744e2011-11-30 15:57:28 +000099 utf8_buffer_[utf8_pos_++] = static_cast<char>(c);
100 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100101 int char_length = unibrow::Utf8::Length(c, previous);
Ben Murdoch257744e2011-11-30 15:57:28 +0000102 if (utf8_pos_ + char_length > kUtf8BufferSize) break;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100103 unibrow::Utf8::Encode(utf8_buffer_ + utf8_pos_, c, previous);
Ben Murdoch257744e2011-11-30 15:57:28 +0000104 utf8_pos_ += char_length;
105 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100106 previous = c;
Ben Murdoch257744e2011-11-30 15:57:28 +0000107 }
108 }
109
110 void AppendBytes(const char* bytes, int size) {
111 size = Min(size, kUtf8BufferSize - utf8_pos_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 MemCopy(utf8_buffer_ + utf8_pos_, bytes, size);
Ben Murdoch257744e2011-11-30 15:57:28 +0000113 utf8_pos_ += size;
114 }
115
116 void AppendBytes(const char* bytes) {
117 AppendBytes(bytes, StrLength(bytes));
118 }
119
120 void AppendByte(char c) {
121 if (utf8_pos_ >= kUtf8BufferSize) return;
122 utf8_buffer_[utf8_pos_++] = c;
123 }
124
125 void AppendInt(int n) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 int space = kUtf8BufferSize - utf8_pos_;
127 if (space <= 0) return;
128 Vector<char> buffer(utf8_buffer_ + utf8_pos_, space);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129 int size = SNPrintF(buffer, "%d", n);
130 if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
131 utf8_pos_ += size;
132 }
133 }
134
135 void AppendHex(uint32_t n) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136 int space = kUtf8BufferSize - utf8_pos_;
137 if (space <= 0) return;
138 Vector<char> buffer(utf8_buffer_ + utf8_pos_, space);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139 int size = SNPrintF(buffer, "%x", n);
Ben Murdoch257744e2011-11-30 15:57:28 +0000140 if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
141 utf8_pos_ += size;
142 }
143 }
144
145 const char* get() { return utf8_buffer_; }
146 int size() const { return utf8_pos_; }
147
148 private:
149 static const int kUtf8BufferSize = 512;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150 static const int kUtf16BufferSize = kUtf8BufferSize;
Ben Murdoch257744e2011-11-30 15:57:28 +0000151
152 int utf8_pos_;
153 char utf8_buffer_[kUtf8BufferSize];
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100154 uc16 utf16_buffer[kUtf16BufferSize];
Ben Murdoch257744e2011-11-30 15:57:28 +0000155};
156
157
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158CodeEventLogger::CodeEventLogger() : name_buffer_(new NameBuffer) { }
159
160CodeEventLogger::~CodeEventLogger() { delete name_buffer_; }
161
162
163void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
164 Code* code,
165 const char* comment) {
166 name_buffer_->Init(tag);
167 name_buffer_->AppendBytes(comment);
168 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
169}
170
171
172void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
173 Code* code,
174 Name* name) {
175 name_buffer_->Init(tag);
176 name_buffer_->AppendName(name);
177 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
178}
179
180
181void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
182 Code* code,
183 SharedFunctionInfo* shared,
184 CompilationInfo* info,
185 Name* name) {
186 name_buffer_->Init(tag);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 name_buffer_->AppendBytes(ComputeMarker(shared, code));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188 name_buffer_->AppendName(name);
189 LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
190}
191
192
193void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
194 Code* code,
195 SharedFunctionInfo* shared,
196 CompilationInfo* info,
197 Name* source, int line, int column) {
198 name_buffer_->Init(tag);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199 name_buffer_->AppendBytes(ComputeMarker(shared, code));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200 name_buffer_->AppendString(shared->DebugName());
201 name_buffer_->AppendByte(' ');
202 if (source->IsString()) {
203 name_buffer_->AppendString(String::cast(source));
204 } else {
205 name_buffer_->AppendBytes("symbol(hash ");
206 name_buffer_->AppendHex(Name::cast(source)->Hash());
207 name_buffer_->AppendByte(')');
208 }
209 name_buffer_->AppendByte(':');
210 name_buffer_->AppendInt(line);
211 LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
212}
213
214
215void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
216 Code* code,
217 int args_count) {
218 name_buffer_->Init(tag);
219 name_buffer_->AppendInt(args_count);
220 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
221}
222
223
224void CodeEventLogger::RegExpCodeCreateEvent(Code* code, String* source) {
225 name_buffer_->Init(Logger::REG_EXP_TAG);
226 name_buffer_->AppendString(source);
227 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
228}
229
230
231// Linux perf tool logging support
232class PerfBasicLogger : public CodeEventLogger {
233 public:
234 PerfBasicLogger();
235 virtual ~PerfBasicLogger();
236
237 virtual void CodeMoveEvent(Address from, Address to) { }
238 virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
239 virtual void CodeDeleteEvent(Address from) { }
240
241 private:
242 virtual void LogRecordedBuffer(Code* code,
243 SharedFunctionInfo* shared,
244 const char* name,
245 int length);
246
247 // Extension added to V8 log file name to get the low-level log name.
248 static const char kFilenameFormatString[];
249 static const int kFilenameBufferPadding;
250
251 // File buffer size of the low-level log. We don't use the default to
252 // minimize the associated overhead.
253 static const int kLogBufferSize = 2 * MB;
254
255 FILE* perf_output_handle_;
256};
257
258const char PerfBasicLogger::kFilenameFormatString[] = "/tmp/perf-%d.map";
259// Extra space for the PID in the filename
260const int PerfBasicLogger::kFilenameBufferPadding = 16;
261
262PerfBasicLogger::PerfBasicLogger()
263 : perf_output_handle_(NULL) {
264 // Open the perf JIT dump file.
265 int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
266 ScopedVector<char> perf_dump_name(bufferSize);
267 int size = SNPrintF(
268 perf_dump_name,
269 kFilenameFormatString,
270 base::OS::GetCurrentProcessId());
271 CHECK_NE(size, -1);
272 perf_output_handle_ =
273 base::OS::FOpen(perf_dump_name.start(), base::OS::LogFileOpenMode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000274 CHECK_NOT_NULL(perf_output_handle_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275 setvbuf(perf_output_handle_, NULL, _IOFBF, kLogBufferSize);
276}
277
278
279PerfBasicLogger::~PerfBasicLogger() {
280 fclose(perf_output_handle_);
281 perf_output_handle_ = NULL;
282}
283
284
285void PerfBasicLogger::LogRecordedBuffer(Code* code,
286 SharedFunctionInfo*,
287 const char* name,
288 int length) {
289 DCHECK(code->instruction_start() == code->address() + Code::kHeaderSize);
290
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 if (FLAG_perf_basic_prof_only_functions &&
292 (code->kind() != Code::FUNCTION &&
293 code->kind() != Code::OPTIMIZED_FUNCTION)) {
294 return;
295 }
296
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 base::OS::FPrint(perf_output_handle_, "%llx %x %.*s\n",
298 reinterpret_cast<uint64_t>(code->instruction_start()),
299 code->instruction_size(), length, name);
300}
301
302
303// Low-level logging support.
304#define LL_LOG(Call) if (ll_logger_) ll_logger_->Call;
305
306class LowLevelLogger : public CodeEventLogger {
307 public:
308 explicit LowLevelLogger(const char* file_name);
309 virtual ~LowLevelLogger();
310
311 virtual void CodeMoveEvent(Address from, Address to);
312 virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
313 virtual void CodeDeleteEvent(Address from);
314 virtual void SnapshotPositionEvent(Address addr, int pos);
315 virtual void CodeMovingGCEvent();
316
317 private:
318 virtual void LogRecordedBuffer(Code* code,
319 SharedFunctionInfo* shared,
320 const char* name,
321 int length);
322
323 // Low-level profiling event structures.
324 struct CodeCreateStruct {
325 static const char kTag = 'C';
326
327 int32_t name_size;
328 Address code_address;
329 int32_t code_size;
330 };
331
332
333 struct CodeMoveStruct {
334 static const char kTag = 'M';
335
336 Address from_address;
337 Address to_address;
338 };
339
340
341 struct CodeDeleteStruct {
342 static const char kTag = 'D';
343
344 Address address;
345 };
346
347
348 struct SnapshotPositionStruct {
349 static const char kTag = 'P';
350
351 Address address;
352 int32_t position;
353 };
354
355
356 static const char kCodeMovingGCTag = 'G';
357
358
359 // Extension added to V8 log file name to get the low-level log name.
360 static const char kLogExt[];
361
362 // File buffer size of the low-level log. We don't use the default to
363 // minimize the associated overhead.
364 static const int kLogBufferSize = 2 * MB;
365
366 void LogCodeInfo();
367 void LogWriteBytes(const char* bytes, int size);
368
369 template <typename T>
370 void LogWriteStruct(const T& s) {
371 char tag = T::kTag;
372 LogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag));
373 LogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s));
374 }
375
376 FILE* ll_output_handle_;
377};
378
379const char LowLevelLogger::kLogExt[] = ".ll";
380
381LowLevelLogger::LowLevelLogger(const char* name)
382 : ll_output_handle_(NULL) {
383 // Open the low-level log file.
384 size_t len = strlen(name);
385 ScopedVector<char> ll_name(static_cast<int>(len + sizeof(kLogExt)));
386 MemCopy(ll_name.start(), name, len);
387 MemCopy(ll_name.start() + len, kLogExt, sizeof(kLogExt));
388 ll_output_handle_ =
389 base::OS::FOpen(ll_name.start(), base::OS::LogFileOpenMode);
390 setvbuf(ll_output_handle_, NULL, _IOFBF, kLogBufferSize);
391
392 LogCodeInfo();
393}
394
395
396LowLevelLogger::~LowLevelLogger() {
397 fclose(ll_output_handle_);
398 ll_output_handle_ = NULL;
399}
400
401
402void LowLevelLogger::LogCodeInfo() {
403#if V8_TARGET_ARCH_IA32
404 const char arch[] = "ia32";
405#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
406 const char arch[] = "x64";
407#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
408 const char arch[] = "x32";
409#elif V8_TARGET_ARCH_ARM
410 const char arch[] = "arm";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000411#elif V8_TARGET_ARCH_PPC
412 const char arch[] = "ppc";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413#elif V8_TARGET_ARCH_MIPS
414 const char arch[] = "mips";
415#elif V8_TARGET_ARCH_X87
416 const char arch[] = "x87";
417#elif V8_TARGET_ARCH_ARM64
418 const char arch[] = "arm64";
419#else
420 const char arch[] = "unknown";
421#endif
422 LogWriteBytes(arch, sizeof(arch));
423}
424
425
426void LowLevelLogger::LogRecordedBuffer(Code* code,
427 SharedFunctionInfo*,
428 const char* name,
429 int length) {
430 CodeCreateStruct event;
431 event.name_size = length;
432 event.code_address = code->instruction_start();
433 DCHECK(event.code_address == code->address() + Code::kHeaderSize);
434 event.code_size = code->instruction_size();
435 LogWriteStruct(event);
436 LogWriteBytes(name, length);
437 LogWriteBytes(
438 reinterpret_cast<const char*>(code->instruction_start()),
439 code->instruction_size());
440}
441
442
443void LowLevelLogger::CodeMoveEvent(Address from, Address to) {
444 CodeMoveStruct event;
445 event.from_address = from + Code::kHeaderSize;
446 event.to_address = to + Code::kHeaderSize;
447 LogWriteStruct(event);
448}
449
450
451void LowLevelLogger::CodeDeleteEvent(Address from) {
452 CodeDeleteStruct event;
453 event.address = from + Code::kHeaderSize;
454 LogWriteStruct(event);
455}
456
457
458void LowLevelLogger::SnapshotPositionEvent(Address addr, int pos) {
459 SnapshotPositionStruct event;
460 event.address = addr + Code::kHeaderSize;
461 event.position = pos;
462 LogWriteStruct(event);
463}
464
465
466void LowLevelLogger::LogWriteBytes(const char* bytes, int size) {
467 size_t rv = fwrite(bytes, 1, size, ll_output_handle_);
468 DCHECK(static_cast<size_t>(size) == rv);
469 USE(rv);
470}
471
472
473void LowLevelLogger::CodeMovingGCEvent() {
474 const char tag = kCodeMovingGCTag;
475
476 LogWriteBytes(&tag, sizeof(tag));
477}
478
479
480#define JIT_LOG(Call) if (jit_logger_) jit_logger_->Call;
481
482
483class JitLogger : public CodeEventLogger {
484 public:
485 explicit JitLogger(JitCodeEventHandler code_event_handler);
486
487 virtual void CodeMoveEvent(Address from, Address to);
488 virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
489 virtual void CodeDeleteEvent(Address from);
490 virtual void AddCodeLinePosInfoEvent(
491 void* jit_handler_data,
492 int pc_offset,
493 int position,
494 JitCodeEvent::PositionType position_type);
495
496 void* StartCodePosInfoEvent();
497 void EndCodePosInfoEvent(Code* code, void* jit_handler_data);
498
499 private:
500 virtual void LogRecordedBuffer(Code* code,
501 SharedFunctionInfo* shared,
502 const char* name,
503 int length);
504
505 JitCodeEventHandler code_event_handler_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000506 base::Mutex logger_mutex_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000507};
508
509
510JitLogger::JitLogger(JitCodeEventHandler code_event_handler)
511 : code_event_handler_(code_event_handler) {
512}
513
514
515void JitLogger::LogRecordedBuffer(Code* code,
516 SharedFunctionInfo* shared,
517 const char* name,
518 int length) {
519 JitCodeEvent event;
520 memset(&event, 0, sizeof(event));
521 event.type = JitCodeEvent::CODE_ADDED;
522 event.code_start = code->instruction_start();
523 event.code_len = code->instruction_size();
524 Handle<SharedFunctionInfo> shared_function_handle;
525 if (shared && shared->script()->IsScript()) {
526 shared_function_handle = Handle<SharedFunctionInfo>(shared);
527 }
528 event.script = ToApiHandle<v8::UnboundScript>(shared_function_handle);
529 event.name.str = name;
530 event.name.len = length;
531 code_event_handler_(&event);
532}
533
534
535void JitLogger::CodeMoveEvent(Address from, Address to) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536 base::LockGuard<base::Mutex> guard(&logger_mutex_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537 Code* from_code = Code::cast(HeapObject::FromAddress(from));
538
539 JitCodeEvent event;
540 event.type = JitCodeEvent::CODE_MOVED;
541 event.code_start = from_code->instruction_start();
542 event.code_len = from_code->instruction_size();
543
544 // Calculate the header size.
545 const size_t header_size =
546 from_code->instruction_start() - reinterpret_cast<byte*>(from_code);
547
548 // Calculate the new start address of the instructions.
549 event.new_code_start =
550 reinterpret_cast<byte*>(HeapObject::FromAddress(to)) + header_size;
551
552 code_event_handler_(&event);
553}
554
555
556void JitLogger::CodeDeleteEvent(Address from) {
557 Code* from_code = Code::cast(HeapObject::FromAddress(from));
558
559 JitCodeEvent event;
560 event.type = JitCodeEvent::CODE_REMOVED;
561 event.code_start = from_code->instruction_start();
562 event.code_len = from_code->instruction_size();
563
564 code_event_handler_(&event);
565}
566
567void JitLogger::AddCodeLinePosInfoEvent(
568 void* jit_handler_data,
569 int pc_offset,
570 int position,
571 JitCodeEvent::PositionType position_type) {
572 JitCodeEvent event;
573 memset(&event, 0, sizeof(event));
574 event.type = JitCodeEvent::CODE_ADD_LINE_POS_INFO;
575 event.user_data = jit_handler_data;
576 event.line_info.offset = pc_offset;
577 event.line_info.pos = position;
578 event.line_info.position_type = position_type;
579
580 code_event_handler_(&event);
581}
582
583
584void* JitLogger::StartCodePosInfoEvent() {
585 JitCodeEvent event;
586 memset(&event, 0, sizeof(event));
587 event.type = JitCodeEvent::CODE_START_LINE_INFO_RECORDING;
588
589 code_event_handler_(&event);
590 return event.user_data;
591}
592
593
594void JitLogger::EndCodePosInfoEvent(Code* code, void* jit_handler_data) {
595 JitCodeEvent event;
596 memset(&event, 0, sizeof(event));
597 event.type = JitCodeEvent::CODE_END_LINE_INFO_RECORDING;
598 event.code_start = code->instruction_start();
599 event.user_data = jit_handler_data;
600
601 code_event_handler_(&event);
602}
603
604
605// The Profiler samples pc and sp values for the main thread.
606// Each sample is appended to a circular buffer.
607// An independent thread removes data and writes it to the log.
608// This design minimizes the time spent in the sampler.
609//
610class Profiler: public base::Thread {
611 public:
612 explicit Profiler(Isolate* isolate);
613 void Engage();
614 void Disengage();
615
616 // Inserts collected profiling data into buffer.
617 void Insert(TickSample* sample) {
618 if (paused_)
619 return;
620
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400621 if (Succ(head_) == static_cast<int>(base::NoBarrier_Load(&tail_))) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622 overflow_ = true;
623 } else {
624 buffer_[head_] = *sample;
625 head_ = Succ(head_);
626 buffer_semaphore_.Signal(); // Tell we have an element.
627 }
628 }
629
630 virtual void Run();
631
632 // Pause and Resume TickSample data collection.
633 void pause() { paused_ = true; }
634 void resume() { paused_ = false; }
635
636 private:
637 // Waits for a signal and removes profiling data.
638 bool Remove(TickSample* sample) {
639 buffer_semaphore_.Wait(); // Wait for an element.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400640 *sample = buffer_[base::NoBarrier_Load(&tail_)];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641 bool result = overflow_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400642 base::NoBarrier_Store(&tail_, static_cast<base::Atomic32>(
643 Succ(base::NoBarrier_Load(&tail_))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000644 overflow_ = false;
645 return result;
646 }
647
648 // Returns the next index in the cyclic buffer.
649 int Succ(int index) { return (index + 1) % kBufferSize; }
650
651 Isolate* isolate_;
652 // Cyclic buffer for communicating profiling samples
653 // between the signal handler and the worker thread.
654 static const int kBufferSize = 128;
655 TickSample buffer_[kBufferSize]; // Buffer storage.
656 int head_; // Index to the buffer head.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400657 base::Atomic32 tail_; // Index to the buffer tail.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000658 bool overflow_; // Tell whether a buffer overflow has occurred.
659 // Sempahore used for buffer synchronization.
660 base::Semaphore buffer_semaphore_;
661
662 // Tells whether profiler is engaged, that is, processing thread is stated.
663 bool engaged_;
664
665 // Tells whether worker thread should continue running.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400666 base::Atomic32 running_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000667
668 // Tells whether we are currently recording tick samples.
669 bool paused_;
670};
671
672
673//
674// Ticker used to provide ticks to the profiler and the sliding state
675// window.
676//
677class Ticker: public Sampler {
678 public:
679 Ticker(Isolate* isolate, int interval):
680 Sampler(isolate, interval),
681 profiler_(NULL) {}
682
683 ~Ticker() { if (IsActive()) Stop(); }
684
685 virtual void Tick(TickSample* sample) {
686 if (profiler_) profiler_->Insert(sample);
687 }
688
689 void SetProfiler(Profiler* profiler) {
690 DCHECK(profiler_ == NULL);
691 profiler_ = profiler;
692 IncreaseProfilingDepth();
693 if (!IsActive()) Start();
694 }
695
696 void ClearProfiler() {
697 profiler_ = NULL;
698 if (IsActive()) Stop();
699 DecreaseProfilingDepth();
700 }
701
702 private:
703 Profiler* profiler_;
704};
705
706
707//
708// Profiler implementation.
709//
710Profiler::Profiler(Isolate* isolate)
711 : base::Thread(Options("v8:Profiler")),
712 isolate_(isolate),
713 head_(0),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000714 overflow_(false),
715 buffer_semaphore_(0),
716 engaged_(false),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400717 paused_(false) {
718 base::NoBarrier_Store(&tail_, 0);
719 base::NoBarrier_Store(&running_, 0);
720}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000721
722
723void Profiler::Engage() {
724 if (engaged_) return;
725 engaged_ = true;
726
727 std::vector<base::OS::SharedLibraryAddress> addresses =
728 base::OS::GetSharedLibraryAddresses();
729 for (size_t i = 0; i < addresses.size(); ++i) {
730 LOG(isolate_, SharedLibraryEvent(
731 addresses[i].library_path, addresses[i].start, addresses[i].end));
732 }
733
734 // Start thread processing the profiler buffer.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400735 base::NoBarrier_Store(&running_, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000736 Start();
737
738 // Register to get ticks.
739 Logger* logger = isolate_->logger();
740 logger->ticker_->SetProfiler(this);
741
742 logger->ProfilerBeginEvent();
743}
744
745
746void Profiler::Disengage() {
747 if (!engaged_) return;
748
749 // Stop receiving ticks.
750 isolate_->logger()->ticker_->ClearProfiler();
751
752 // Terminate the worker thread by setting running_ to false,
753 // inserting a fake element in the queue and then wait for
754 // the thread to terminate.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400755 base::NoBarrier_Store(&running_, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000756 TickSample sample;
757 // Reset 'paused_' flag, otherwise semaphore may not be signalled.
758 resume();
759 Insert(&sample);
760 Join();
761
762 LOG(isolate_, UncheckedStringEvent("profiler", "end"));
763}
764
765
766void Profiler::Run() {
767 TickSample sample;
768 bool overflow = Remove(&sample);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400769 while (base::NoBarrier_Load(&running_)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000770 LOG(isolate_, TickEvent(&sample, overflow));
771 overflow = Remove(&sample);
772 }
773}
774
775
776//
777// Logger class implementation.
778//
779
780Logger::Logger(Isolate* isolate)
781 : isolate_(isolate),
782 ticker_(NULL),
Steve Block44f0eee2011-05-26 01:26:41 +0100783 profiler_(NULL),
Steve Block44f0eee2011-05-26 01:26:41 +0100784 log_events_(NULL),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000785 is_logging_(false),
Steve Block44f0eee2011-05-26 01:26:41 +0100786 log_(new Log(this)),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000787 perf_basic_logger_(NULL),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000788 ll_logger_(NULL),
789 jit_logger_(NULL),
790 listeners_(5),
791 is_initialized_(false) {
Steve Block44f0eee2011-05-26 01:26:41 +0100792}
793
Ben Murdoch257744e2011-11-30 15:57:28 +0000794
Steve Block44f0eee2011-05-26 01:26:41 +0100795Logger::~Logger() {
796 delete log_;
797}
Steve Blocka7e24c12009-10-30 11:49:00 +0000798
Ben Murdoch257744e2011-11-30 15:57:28 +0000799
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000800void Logger::addCodeEventListener(CodeEventListener* listener) {
801 DCHECK(!hasCodeEventListener(listener));
802 listeners_.Add(listener);
803}
804
805
806void Logger::removeCodeEventListener(CodeEventListener* listener) {
807 DCHECK(hasCodeEventListener(listener));
808 listeners_.RemoveElement(listener);
809}
810
811
812bool Logger::hasCodeEventListener(CodeEventListener* listener) {
813 return listeners_.Contains(listener);
814}
Steve Blocka7e24c12009-10-30 11:49:00 +0000815
816
817void Logger::ProfilerBeginEvent() {
Steve Block44f0eee2011-05-26 01:26:41 +0100818 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000819 Log::MessageBuilder msg(log_);
820 msg.Append("profiler,\"begin\",%d", kSamplingIntervalMs);
Steve Blocka7e24c12009-10-30 11:49:00 +0000821 msg.WriteToLogFile();
822}
823
Steve Blocka7e24c12009-10-30 11:49:00 +0000824
Steve Blocka7e24c12009-10-30 11:49:00 +0000825void Logger::StringEvent(const char* name, const char* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000826 if (FLAG_log) UncheckedStringEvent(name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000827}
828
829
Steve Blocka7e24c12009-10-30 11:49:00 +0000830void Logger::UncheckedStringEvent(const char* name, const char* value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100831 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000832 Log::MessageBuilder msg(log_);
833 msg.Append("%s,\"%s\"", name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000834 msg.WriteToLogFile();
835}
Steve Blocka7e24c12009-10-30 11:49:00 +0000836
837
838void Logger::IntEvent(const char* name, int value) {
Steve Block6ded16b2010-05-10 14:33:55 +0100839 if (FLAG_log) UncheckedIntEvent(name, value);
Steve Block6ded16b2010-05-10 14:33:55 +0100840}
841
842
Ben Murdochf87a2032010-10-22 12:50:53 +0100843void Logger::IntPtrTEvent(const char* name, intptr_t value) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100844 if (FLAG_log) UncheckedIntPtrTEvent(name, value);
Ben Murdochf87a2032010-10-22 12:50:53 +0100845}
846
847
Steve Block6ded16b2010-05-10 14:33:55 +0100848void Logger::UncheckedIntEvent(const char* name, int value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100849 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000850 Log::MessageBuilder msg(log_);
851 msg.Append("%s,%d", name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000852 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000853}
854
855
Ben Murdochf87a2032010-10-22 12:50:53 +0100856void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100857 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000858 Log::MessageBuilder msg(log_);
859 msg.Append("%s,%" V8_PTR_PREFIX "d", name, value);
Ben Murdochf87a2032010-10-22 12:50:53 +0100860 msg.WriteToLogFile();
861}
Ben Murdochf87a2032010-10-22 12:50:53 +0100862
863
Steve Blocka7e24c12009-10-30 11:49:00 +0000864void Logger::HandleEvent(const char* name, Object** location) {
Steve Block44f0eee2011-05-26 01:26:41 +0100865 if (!log_->IsEnabled() || !FLAG_log_handles) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000866 Log::MessageBuilder msg(log_);
867 msg.Append("%s,0x%" V8PRIxPTR, name, location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000868 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000869}
870
871
Steve Blocka7e24c12009-10-30 11:49:00 +0000872// ApiEvent is private so all the calls come from the Logger class. It is the
873// caller's responsibility to ensure that log is enabled and that
874// FLAG_log_api is true.
875void Logger::ApiEvent(const char* format, ...) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000876 DCHECK(log_->IsEnabled() && FLAG_log_api);
877 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000878 va_list ap;
879 va_start(ap, format);
880 msg.AppendVA(format, ap);
881 va_end(ap);
882 msg.WriteToLogFile();
883}
Steve Blocka7e24c12009-10-30 11:49:00 +0000884
885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886void Logger::ApiSecurityCheck() {
Steve Block44f0eee2011-05-26 01:26:41 +0100887 if (!log_->IsEnabled() || !FLAG_log_api) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000888 ApiEvent("api,check-security");
Steve Blocka7e24c12009-10-30 11:49:00 +0000889}
890
891
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000892void Logger::SharedLibraryEvent(const std::string& library_path,
Steve Blocka7e24c12009-10-30 11:49:00 +0000893 uintptr_t start,
894 uintptr_t end) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000895 if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000896 Log::MessageBuilder msg(log_);
897 msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR,
898 library_path.c_str(), start, end);
Steve Blocka7e24c12009-10-30 11:49:00 +0000899 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000900}
901
902
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000903void Logger::CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) {
904 PROFILER_LOG(CodeDeoptEvent(code, pc, fp_to_sp_delta));
905 if (!log_->IsEnabled() || !FLAG_log_internal_timer_events) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906 Log::MessageBuilder msg(log_);
907 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
908 msg.Append("code-deopt,%ld,%d", since_epoch, code->CodeSize());
Steve Blocka7e24c12009-10-30 11:49:00 +0000909 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000910}
911
912
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913void Logger::CurrentTimeEvent() {
914 if (!log_->IsEnabled()) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000915 DCHECK(FLAG_log_timer_events || FLAG_prof_cpp);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000916 Log::MessageBuilder msg(log_);
917 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
918 msg.Append("current-time,%ld", since_epoch);
919 msg.WriteToLogFile();
920}
921
922
923void Logger::TimerEvent(Logger::StartEnd se, const char* name) {
924 if (!log_->IsEnabled()) return;
925 DCHECK(FLAG_log_internal_timer_events);
926 Log::MessageBuilder msg(log_);
927 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
928 const char* format = (se == START) ? "timer-event-start,\"%s\",%ld"
929 : "timer-event-end,\"%s\",%ld";
930 msg.Append(format, name, since_epoch);
931 msg.WriteToLogFile();
932}
933
934
935void Logger::EnterExternal(Isolate* isolate) {
936 LOG(isolate, TimerEvent(START, TimerEventExternal::name()));
937 DCHECK(isolate->current_vm_state() == JS);
938 isolate->set_current_vm_state(EXTERNAL);
939}
940
941
942void Logger::LeaveExternal(Isolate* isolate) {
943 LOG(isolate, TimerEvent(END, TimerEventExternal::name()));
944 DCHECK(isolate->current_vm_state() == EXTERNAL);
945 isolate->set_current_vm_state(JS);
946}
947
948
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000949template <class TimerEvent>
950void TimerEventScope<TimerEvent>::LogTimerEvent(Logger::StartEnd se) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400951 Logger::CallEventLogger(isolate_, TimerEvent::name(), se,
952 TimerEvent::expose_to_api());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000953}
954
955
956// Instantiate template methods.
957#define V(TimerName, expose) \
958 template void TimerEventScope<TimerEvent##TimerName>::LogTimerEvent( \
959 Logger::StartEnd se);
960TIMER_EVENTS_LIST(V)
961#undef V
962
963
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000964namespace {
965// Emits the source code of a regexp. Used by regexp events.
966void LogRegExpSource(Handle<JSRegExp> regexp, Isolate* isolate,
967 Log::MessageBuilder* msg) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000968 // Prints "/" + re.source + "/" +
969 // (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
Steve Blocka7e24c12009-10-30 11:49:00 +0000970
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000971 Handle<Object> source =
972 Object::GetProperty(isolate, regexp, "source").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000973 if (!source->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000974 msg->Append("no source");
Steve Blocka7e24c12009-10-30 11:49:00 +0000975 return;
976 }
977
978 switch (regexp->TypeTag()) {
979 case JSRegExp::ATOM:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980 msg->Append('a');
Steve Blocka7e24c12009-10-30 11:49:00 +0000981 break;
982 default:
983 break;
984 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000985 msg->Append('/');
986 msg->AppendDetailed(*Handle<String>::cast(source), false);
987 msg->Append('/');
Steve Blocka7e24c12009-10-30 11:49:00 +0000988
989 // global flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000990 Handle<Object> global =
991 Object::GetProperty(isolate, regexp, "global").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000992 if (global->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000993 msg->Append('g');
Steve Blocka7e24c12009-10-30 11:49:00 +0000994 }
995 // ignorecase flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000996 Handle<Object> ignorecase =
997 Object::GetProperty(isolate, regexp, "ignoreCase").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000998 if (ignorecase->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 msg->Append('i');
Steve Blocka7e24c12009-10-30 11:49:00 +00001000 }
1001 // multiline flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001002 Handle<Object> multiline =
1003 Object::GetProperty(isolate, regexp, "multiline").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001004 if (multiline->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 msg->Append('m');
Steve Blocka7e24c12009-10-30 11:49:00 +00001006 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001007}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001008} // namespace
Steve Blocka7e24c12009-10-30 11:49:00 +00001009
1010
1011void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
Steve Block44f0eee2011-05-26 01:26:41 +01001012 if (!log_->IsEnabled() || !FLAG_log_regexp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001013 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001014 msg.Append("regexp-compile,");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001015 LogRegExpSource(regexp, isolate_, &msg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001016 msg.Append(in_cache ? ",hit" : ",miss");
Steve Blocka7e24c12009-10-30 11:49:00 +00001017 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001018}
1019
1020
Steve Blocka7e24c12009-10-30 11:49:00 +00001021void Logger::ApiNamedPropertyAccess(const char* tag,
1022 JSObject* holder,
1023 Object* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001024 DCHECK(name->IsName());
Steve Block44f0eee2011-05-26 01:26:41 +01001025 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001026 String* class_name_obj = holder->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001027 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +00001028 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001029 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001030 base::SmartArrayPointer<char> property_name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001031 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1032 ApiEvent("api,%s,\"%s\",\"%s\"", tag, class_name.get(),
1033 property_name.get());
1034 } else {
1035 Symbol* symbol = Symbol::cast(name);
1036 uint32_t hash = symbol->Hash();
1037 if (symbol->name()->IsUndefined()) {
1038 ApiEvent("api,%s,\"%s\",symbol(hash %x)", tag, class_name.get(), hash);
1039 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001040 base::SmartArrayPointer<char> str =
1041 String::cast(symbol->name())
1042 ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001043 ApiEvent("api,%s,\"%s\",symbol(\"%s\" hash %x)", tag, class_name.get(),
1044 str.get(), hash);
1045 }
1046 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001047}
1048
1049void Logger::ApiIndexedPropertyAccess(const char* tag,
1050 JSObject* holder,
1051 uint32_t index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001052 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001053 String* class_name_obj = holder->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001054 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +00001055 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056 ApiEvent("api,%s,\"%s\",%u", tag, class_name.get(), index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001057}
1058
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001059
Steve Blocka7e24c12009-10-30 11:49:00 +00001060void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
Steve Block44f0eee2011-05-26 01:26:41 +01001061 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001062 String* class_name_obj = object->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001063 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +00001064 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001065 ApiEvent("api,%s,\"%s\"", tag, class_name.get());
Steve Blocka7e24c12009-10-30 11:49:00 +00001066}
1067
1068
1069void Logger::ApiEntryCall(const char* name) {
Steve Block44f0eee2011-05-26 01:26:41 +01001070 if (!log_->IsEnabled() || !FLAG_log_api) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001071 ApiEvent("api,%s", name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001072}
1073
1074
1075void Logger::NewEvent(const char* name, void* object, size_t size) {
Steve Block44f0eee2011-05-26 01:26:41 +01001076 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001077 Log::MessageBuilder msg(log_);
1078 msg.Append("new,%s,0x%" V8PRIxPTR ",%u", name, object,
Steve Blocka7e24c12009-10-30 11:49:00 +00001079 static_cast<unsigned int>(size));
1080 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001081}
1082
1083
1084void Logger::DeleteEvent(const char* name, void* object) {
Steve Block44f0eee2011-05-26 01:26:41 +01001085 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001086 Log::MessageBuilder msg(log_);
1087 msg.Append("delete,%s,0x%" V8PRIxPTR, name, object);
Steve Blocka7e24c12009-10-30 11:49:00 +00001088 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001089}
1090
1091
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001092void Logger::CallbackEventInternal(const char* prefix, Name* name,
Steve Blockd0582a62009-12-15 09:54:21 +00001093 Address entry_point) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001094 if (!FLAG_log_code || !log_->IsEnabled()) return;
1095 Log::MessageBuilder msg(log_);
1096 msg.Append("%s,%s,-2,",
Ben Murdochb0fe1622011-05-05 13:52:32 +01001097 kLogEventsNames[CODE_CREATION_EVENT],
1098 kLogEventsNames[CALLBACK_TAG]);
Steve Blockd0582a62009-12-15 09:54:21 +00001099 msg.AppendAddress(entry_point);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001100 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101 base::SmartArrayPointer<char> str =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1103 msg.Append(",1,\"%s%s\"", prefix, str.get());
1104 } else {
1105 Symbol* symbol = Symbol::cast(name);
1106 if (symbol->name()->IsUndefined()) {
1107 msg.Append(",1,symbol(hash %x)", prefix, symbol->Hash());
1108 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001109 base::SmartArrayPointer<char> str =
1110 String::cast(symbol->name())
1111 ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112 msg.Append(",1,symbol(\"%s\" hash %x)", prefix, str.get(),
1113 symbol->Hash());
1114 }
1115 }
Steve Blockd0582a62009-12-15 09:54:21 +00001116 msg.WriteToLogFile();
1117}
Steve Blockd0582a62009-12-15 09:54:21 +00001118
1119
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001120void Logger::CallbackEvent(Name* name, Address entry_point) {
1121 PROFILER_LOG(CallbackEvent(name, entry_point));
1122 CallbackEventInternal("", name, entry_point);
Steve Blockd0582a62009-12-15 09:54:21 +00001123}
1124
1125
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001126void Logger::GetterCallbackEvent(Name* name, Address entry_point) {
1127 PROFILER_LOG(GetterCallbackEvent(name, entry_point));
1128 CallbackEventInternal("get ", name, entry_point);
Steve Blockd0582a62009-12-15 09:54:21 +00001129}
1130
1131
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001132void Logger::SetterCallbackEvent(Name* name, Address entry_point) {
1133 PROFILER_LOG(SetterCallbackEvent(name, entry_point));
1134 CallbackEventInternal("set ", name, entry_point);
1135}
1136
1137
1138static void AppendCodeCreateHeader(Log::MessageBuilder* msg,
1139 Logger::LogEventsAndTags tag,
1140 Code* code) {
1141 DCHECK(msg);
1142 msg->Append("%s,%s,%d,",
1143 kLogEventsNames[Logger::CODE_CREATION_EVENT],
1144 kLogEventsNames[tag],
1145 code->kind());
1146 msg->AppendAddress(code->address());
1147 msg->Append(",%d,", code->ExecutableSize());
Steve Blockd0582a62009-12-15 09:54:21 +00001148}
1149
1150
Steve Blocka7e24c12009-10-30 11:49:00 +00001151void Logger::CodeCreateEvent(LogEventsAndTags tag,
1152 Code* code,
1153 const char* comment) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001154 PROFILER_LOG(CodeCreateEvent(tag, code, comment));
1155
1156 if (!is_logging_code_events()) return;
1157 CALL_LISTENERS(CodeCreateEvent(tag, code, comment));
1158
1159 if (!FLAG_log_code || !log_->IsEnabled()) return;
1160 Log::MessageBuilder msg(log_);
1161 AppendCodeCreateHeader(&msg, tag, code);
1162 msg.AppendDoubleQuotedString(comment);
Steve Blocka7e24c12009-10-30 11:49:00 +00001163 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001164}
1165
1166
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001167void Logger::CodeCreateEvent(LogEventsAndTags tag,
1168 Code* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001169 Name* name) {
1170 PROFILER_LOG(CodeCreateEvent(tag, code, name));
1171
1172 if (!is_logging_code_events()) return;
1173 CALL_LISTENERS(CodeCreateEvent(tag, code, name));
1174
1175 if (!FLAG_log_code || !log_->IsEnabled()) return;
1176 Log::MessageBuilder msg(log_);
1177 AppendCodeCreateHeader(&msg, tag, code);
1178 if (name->IsString()) {
1179 msg.Append('"');
1180 msg.AppendDetailed(String::cast(name), false);
1181 msg.Append('"');
1182 } else {
1183 msg.AppendSymbolName(Symbol::cast(name));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001184 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001185 msg.WriteToLogFile();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001186}
1187
1188
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001189void Logger::CodeCreateEvent(LogEventsAndTags tag,
1190 Code* code,
1191 SharedFunctionInfo* shared,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 CompilationInfo* info,
1193 Name* name) {
1194 PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, name));
Steve Block44f0eee2011-05-26 01:26:41 +01001195
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001196 if (!is_logging_code_events()) return;
1197 CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, name));
1198
1199 if (!FLAG_log_code || !log_->IsEnabled()) return;
1200 if (code == isolate_->builtins()->builtin(Builtins::kCompileLazy)) return;
1201
1202 Log::MessageBuilder msg(log_);
1203 AppendCodeCreateHeader(&msg, tag, code);
1204 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001205 base::SmartArrayPointer<char> str =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001206 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1207 msg.Append("\"%s\"", str.get());
1208 } else {
1209 msg.AppendSymbolName(Symbol::cast(name));
1210 }
1211 msg.Append(',');
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001212 msg.AppendAddress(shared->address());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213 msg.Append(",%s", ComputeMarker(shared, code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001214 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001215}
1216
1217
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001218// Although, it is possible to extract source and line from
1219// the SharedFunctionInfo object, we left it to caller
1220// to leave logging functions free from heap allocations.
Steve Blocka7e24c12009-10-30 11:49:00 +00001221void Logger::CodeCreateEvent(LogEventsAndTags tag,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001222 Code* code,
1223 SharedFunctionInfo* shared,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001224 CompilationInfo* info,
1225 Name* source, int line, int column) {
1226 PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, source, line, column));
1227
1228 if (!is_logging_code_events()) return;
1229 CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, source, line,
1230 column));
1231
1232 if (!FLAG_log_code || !log_->IsEnabled()) return;
1233 Log::MessageBuilder msg(log_);
1234 AppendCodeCreateHeader(&msg, tag, code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001235 base::SmartArrayPointer<char> name =
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001236 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001237 msg.Append("\"%s ", name.get());
1238 if (source->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001239 base::SmartArrayPointer<char> sourcestr = String::cast(source)->ToCString(
1240 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001241 msg.Append("%s", sourcestr.get());
1242 } else {
1243 msg.AppendSymbolName(Symbol::cast(source));
1244 }
1245 msg.Append(":%d:%d\",", line, column);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001246 msg.AppendAddress(shared->address());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001247 msg.Append(",%s", ComputeMarker(shared, code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001248 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001249}
1250
1251
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001252void Logger::CodeCreateEvent(LogEventsAndTags tag,
1253 Code* code,
1254 int args_count) {
1255 PROFILER_LOG(CodeCreateEvent(tag, code, args_count));
1256
1257 if (!is_logging_code_events()) return;
1258 CALL_LISTENERS(CodeCreateEvent(tag, code, args_count));
1259
1260 if (!FLAG_log_code || !log_->IsEnabled()) return;
1261 Log::MessageBuilder msg(log_);
1262 AppendCodeCreateHeader(&msg, tag, code);
1263 msg.Append("\"args_count: %d\"", args_count);
1264 msg.WriteToLogFile();
1265}
1266
1267
1268void Logger::CodeDisableOptEvent(Code* code,
1269 SharedFunctionInfo* shared) {
1270 PROFILER_LOG(CodeDisableOptEvent(code, shared));
1271
1272 if (!is_logging_code_events()) return;
1273 CALL_LISTENERS(CodeDisableOptEvent(code, shared));
1274
1275 if (!FLAG_log_code || !log_->IsEnabled()) return;
1276 Log::MessageBuilder msg(log_);
1277 msg.Append("%s,", kLogEventsNames[CODE_DISABLE_OPT_EVENT]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001278 base::SmartArrayPointer<char> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001279 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1280 msg.Append("\"%s\",", name.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001281 msg.Append("\"%s\"", GetBailoutReason(shared->disable_optimization_reason()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001282 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001283}
1284
1285
Ben Murdochf87a2032010-10-22 12:50:53 +01001286void Logger::CodeMovingGCEvent() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001287 PROFILER_LOG(CodeMovingGCEvent());
1288
1289 if (!is_logging_code_events()) return;
Ben Murdoch257744e2011-11-30 15:57:28 +00001290 if (!log_->IsEnabled() || !FLAG_ll_prof) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 CALL_LISTENERS(CodeMovingGCEvent());
1292 base::OS::SignalCodeMovingGC();
Ben Murdochf87a2032010-10-22 12:50:53 +01001293}
1294
1295
Steve Blocka7e24c12009-10-30 11:49:00 +00001296void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001297 PROFILER_LOG(RegExpCodeCreateEvent(code, source));
1298
1299 if (!is_logging_code_events()) return;
1300 CALL_LISTENERS(RegExpCodeCreateEvent(code, source));
1301
1302 if (!FLAG_log_code || !log_->IsEnabled()) return;
1303 Log::MessageBuilder msg(log_);
1304 AppendCodeCreateHeader(&msg, REG_EXP_TAG, code);
1305 msg.Append('"');
Steve Blocka7e24c12009-10-30 11:49:00 +00001306 msg.AppendDetailed(source, false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001307 msg.Append('"');
Steve Blocka7e24c12009-10-30 11:49:00 +00001308 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001309}
1310
1311
1312void Logger::CodeMoveEvent(Address from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001313 PROFILER_LOG(CodeMoveEvent(from, to));
1314
1315 if (!is_logging_code_events()) return;
1316 CALL_LISTENERS(CodeMoveEvent(from, to));
Leon Clarked91b9f72010-01-27 17:25:45 +00001317 MoveEventInternal(CODE_MOVE_EVENT, from, to);
Steve Blocka7e24c12009-10-30 11:49:00 +00001318}
1319
1320
1321void Logger::CodeDeleteEvent(Address from) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001322 PROFILER_LOG(CodeDeleteEvent(from));
1323
1324 if (!is_logging_code_events()) return;
1325 CALL_LISTENERS(CodeDeleteEvent(from));
1326
1327 if (!FLAG_log_code || !log_->IsEnabled()) return;
1328 Log::MessageBuilder msg(log_);
1329 msg.Append("%s,", kLogEventsNames[CODE_DELETE_EVENT]);
1330 msg.AppendAddress(from);
1331 msg.WriteToLogFile();
1332}
1333
1334
1335void Logger::CodeLinePosInfoAddPositionEvent(void* jit_handler_data,
1336 int pc_offset,
1337 int position) {
1338 JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1339 pc_offset,
1340 position,
1341 JitCodeEvent::POSITION));
1342}
1343
1344
1345void Logger::CodeLinePosInfoAddStatementPositionEvent(void* jit_handler_data,
1346 int pc_offset,
1347 int position) {
1348 JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1349 pc_offset,
1350 position,
1351 JitCodeEvent::STATEMENT_POSITION));
1352}
1353
1354
1355void Logger::CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder) {
1356 if (jit_logger_ != NULL) {
1357 pos_recorder->AttachJITHandlerData(jit_logger_->StartCodePosInfoEvent());
Ben Murdoch257744e2011-11-30 15:57:28 +00001358 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001359}
1360
1361
1362void Logger::CodeEndLinePosInfoRecordEvent(Code* code,
1363 void* jit_handler_data) {
1364 JIT_LOG(EndCodePosInfoEvent(code, jit_handler_data));
1365}
1366
1367
1368void Logger::CodeNameEvent(Address addr, int pos, const char* code_name) {
1369 if (code_name == NULL) return; // Not a code object.
1370 Log::MessageBuilder msg(log_);
1371 msg.Append("%s,%d,", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
1372 msg.AppendDoubleQuotedString(code_name);
1373 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001374}
1375
1376
Leon Clarkee46be812010-01-19 14:06:41 +00001377void Logger::SnapshotPositionEvent(Address addr, int pos) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001378 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001379 LL_LOG(SnapshotPositionEvent(addr, pos));
Ben Murdoch257744e2011-11-30 15:57:28 +00001380 if (!FLAG_log_snapshot_positions) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001381 Log::MessageBuilder msg(log_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001382 msg.Append("%s,", kLogEventsNames[SNAPSHOT_POSITION_EVENT]);
Leon Clarkee46be812010-01-19 14:06:41 +00001383 msg.AppendAddress(addr);
1384 msg.Append(",%d", pos);
Leon Clarkee46be812010-01-19 14:06:41 +00001385 msg.WriteToLogFile();
Leon Clarkee46be812010-01-19 14:06:41 +00001386}
1387
1388
Steve Block44f0eee2011-05-26 01:26:41 +01001389void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001390 if (!is_logging_code_events()) return;
Steve Block44f0eee2011-05-26 01:26:41 +01001391 MoveEventInternal(SHARED_FUNC_MOVE_EVENT, from, to);
Leon Clarked91b9f72010-01-27 17:25:45 +00001392}
1393
1394
Leon Clarked91b9f72010-01-27 17:25:45 +00001395void Logger::MoveEventInternal(LogEventsAndTags event,
1396 Address from,
1397 Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001398 if (!FLAG_log_code || !log_->IsEnabled()) return;
1399 Log::MessageBuilder msg(log_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001400 msg.Append("%s,", kLogEventsNames[event]);
Leon Clarked91b9f72010-01-27 17:25:45 +00001401 msg.AppendAddress(from);
1402 msg.Append(',');
Ben Murdochb0fe1622011-05-05 13:52:32 +01001403 msg.AppendAddress(to);
Leon Clarked91b9f72010-01-27 17:25:45 +00001404 msg.WriteToLogFile();
1405}
Leon Clarked91b9f72010-01-27 17:25:45 +00001406
1407
Steve Blocka7e24c12009-10-30 11:49:00 +00001408void Logger::ResourceEvent(const char* name, const char* tag) {
Steve Block44f0eee2011-05-26 01:26:41 +01001409 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001410 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001411 msg.Append("%s,%s,", name, tag);
1412
1413 uint32_t sec, usec;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001414 if (base::OS::GetUserTime(&sec, &usec) != -1) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001415 msg.Append("%d,%d,", sec, usec);
1416 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001417 msg.Append("%.0f", base::OS::TimeCurrentMillis());
Steve Blocka7e24c12009-10-30 11:49:00 +00001418 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001419}
1420
1421
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001422void Logger::SuspectReadEvent(Name* name, Object* obj) {
Steve Block44f0eee2011-05-26 01:26:41 +01001423 if (!log_->IsEnabled() || !FLAG_log_suspect) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001424 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001425 String* class_name = obj->IsJSObject()
1426 ? JSObject::cast(obj)->class_name()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001427 : isolate_->heap()->empty_string();
Steve Blocka7e24c12009-10-30 11:49:00 +00001428 msg.Append("suspect-read,");
1429 msg.Append(class_name);
1430 msg.Append(',');
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001431 if (name->IsString()) {
1432 msg.Append('"');
1433 msg.Append(String::cast(name));
1434 msg.Append('"');
1435 } else {
1436 msg.AppendSymbolName(Symbol::cast(name));
1437 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001438 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001439}
1440
1441
1442void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
Steve Block44f0eee2011-05-26 01:26:41 +01001443 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001444 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001445 // Using non-relative system time in order to be able to synchronize with
1446 // external memory profiling events (e.g. DOM memory size).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001447 msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f", space, kind,
1448 base::OS::TimeCurrentMillis());
Steve Blocka7e24c12009-10-30 11:49:00 +00001449 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001450}
1451
1452
1453void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
Steve Block44f0eee2011-05-26 01:26:41 +01001454 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001455 Log::MessageBuilder msg(log_);
1456 msg.Append("heap-sample-end,\"%s\",\"%s\"", space, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001457 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001458}
1459
1460
1461void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
Steve Block44f0eee2011-05-26 01:26:41 +01001462 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001463 Log::MessageBuilder msg(log_);
1464 msg.Append("heap-sample-item,%s,%d,%d", type, number, bytes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001465 msg.WriteToLogFile();
Steve Block3ce2e202009-11-05 08:53:23 +00001466}
1467
1468
Steve Blocka7e24c12009-10-30 11:49:00 +00001469void Logger::DebugTag(const char* call_site_tag) {
Steve Block44f0eee2011-05-26 01:26:41 +01001470 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001471 Log::MessageBuilder msg(log_);
1472 msg.Append("debug-tag,%s", call_site_tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001473 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001474}
1475
1476
1477void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
Steve Block44f0eee2011-05-26 01:26:41 +01001478 if (!log_->IsEnabled() || !FLAG_log) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001479 StringBuilder s(parameter.length() + 1);
1480 for (int i = 0; i < parameter.length(); ++i) {
1481 s.AddCharacter(static_cast<char>(parameter[i]));
1482 }
1483 char* parameter_string = s.Finalize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001484 Log::MessageBuilder msg(log_);
1485 msg.Append("debug-queue-event,%s,%15.3f,%s", event_type,
1486 base::OS::TimeCurrentMillis(), parameter_string);
Steve Blocka7e24c12009-10-30 11:49:00 +00001487 DeleteArray(parameter_string);
1488 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001489}
1490
1491
Steve Blocka7e24c12009-10-30 11:49:00 +00001492void Logger::TickEvent(TickSample* sample, bool overflow) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001493 if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001494 Log::MessageBuilder msg(log_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001495 msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
1496 msg.AppendAddress(sample->pc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001497 msg.Append(",%ld", static_cast<int>(timer_.Elapsed().InMicroseconds()));
Steve Block44f0eee2011-05-26 01:26:41 +01001498 if (sample->has_external_callback) {
1499 msg.Append(",1,");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001500#if USES_FUNCTION_DESCRIPTORS
1501 msg.AppendAddress(*FUNCTION_ENTRYPOINT_ADDRESS(sample->external_callback));
1502#else
Steve Block44f0eee2011-05-26 01:26:41 +01001503 msg.AppendAddress(sample->external_callback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001504#endif
Steve Block44f0eee2011-05-26 01:26:41 +01001505 } else {
1506 msg.Append(",0,");
1507 msg.AppendAddress(sample->tos);
1508 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001509 msg.Append(",%d", static_cast<int>(sample->state));
1510 if (overflow) {
1511 msg.Append(",overflow");
1512 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001513 for (unsigned i = 0; i < sample->frames_count; ++i) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001514 msg.Append(',');
Ben Murdochb0fe1622011-05-05 13:52:32 +01001515 msg.AppendAddress(sample->stack[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001516 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001517 msg.WriteToLogFile();
1518}
1519
1520
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001521void Logger::StopProfiler() {
Steve Block44f0eee2011-05-26 01:26:41 +01001522 if (!log_->IsEnabled()) return;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001523 if (profiler_ != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001524 profiler_->pause();
1525 is_logging_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001526 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001527}
1528
1529
1530// This function can be called when Log's mutex is acquired,
1531// either from main or Profiler's thread.
Steve Block44f0eee2011-05-26 01:26:41 +01001532void Logger::LogFailure() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001533 StopProfiler();
Steve Blocka7e24c12009-10-30 11:49:00 +00001534}
1535
1536
Ben Murdochb0fe1622011-05-05 13:52:32 +01001537class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor {
1538 public:
1539 EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis,
1540 Handle<Code>* code_objects,
1541 int* count)
1542 : sfis_(sfis), code_objects_(code_objects), count_(count) { }
1543
1544 virtual void EnterContext(Context* context) {}
1545 virtual void LeaveContext(Context* context) {}
1546
1547 virtual void VisitFunction(JSFunction* function) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001548 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(function->shared());
1549 Object* maybe_script = sfi->script();
1550 if (maybe_script->IsScript()
1551 && !Script::cast(maybe_script)->HasValidSource()) return;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001552 if (sfis_ != NULL) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001553 sfis_[*count_] = Handle<SharedFunctionInfo>(sfi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001554 }
1555 if (code_objects_ != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001556 DCHECK(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001557 code_objects_[*count_] = Handle<Code>(function->code());
1558 }
1559 *count_ = *count_ + 1;
1560 }
1561
1562 private:
1563 Handle<SharedFunctionInfo>* sfis_;
1564 Handle<Code>* code_objects_;
1565 int* count_;
1566};
1567
1568
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569static int EnumerateCompiledFunctions(Heap* heap,
1570 Handle<SharedFunctionInfo>* sfis,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001571 Handle<Code>* code_objects) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001572 HeapIterator iterator(heap);
1573 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001574 int compiled_funcs_count = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001575
1576 // Iterate the heap to find shared function info objects and record
1577 // the unoptimized code for them.
Leon Clarked91b9f72010-01-27 17:25:45 +00001578 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001579 if (!obj->IsSharedFunctionInfo()) continue;
1580 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
1581 if (sfi->is_compiled()
1582 && (!sfi->script()->IsScript()
1583 || Script::cast(sfi->script())->HasValidSource())) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001584 if (sfis != NULL) {
Steve Block3ce2e202009-11-05 08:53:23 +00001585 sfis[compiled_funcs_count] = Handle<SharedFunctionInfo>(sfi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001586 }
1587 if (code_objects != NULL) {
1588 code_objects[compiled_funcs_count] = Handle<Code>(sfi->code());
1589 }
Steve Block3ce2e202009-11-05 08:53:23 +00001590 ++compiled_funcs_count;
Steve Blocka7e24c12009-10-30 11:49:00 +00001591 }
1592 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001593
1594 // Iterate all optimized functions in all contexts.
1595 EnumerateOptimizedFunctionsVisitor visitor(sfis,
1596 code_objects,
1597 &compiled_funcs_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001598 Deoptimizer::VisitAllOptimizedFunctions(heap->isolate(), &visitor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001599
Steve Block3ce2e202009-11-05 08:53:23 +00001600 return compiled_funcs_count;
1601}
1602
1603
Steve Blockd0582a62009-12-15 09:54:21 +00001604void Logger::LogCodeObject(Object* object) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001605 Code* code_object = Code::cast(object);
1606 LogEventsAndTags tag = Logger::STUB_TAG;
1607 const char* description = "Unknown code from the snapshot";
1608 switch (code_object->kind()) {
1609 case Code::FUNCTION:
1610 case Code::OPTIMIZED_FUNCTION:
1611 return; // We log this later using LogCompiledFunctions.
1612 case Code::BINARY_OP_IC:
1613 case Code::COMPARE_IC: // fall through
1614 case Code::COMPARE_NIL_IC: // fall through
1615 case Code::TO_BOOLEAN_IC: // fall through
1616 case Code::STUB:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001617 description = CodeStub::MajorName(CodeStub::GetMajorKey(code_object));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001618 if (description == NULL)
1619 description = "A stub from the snapshot";
1620 tag = Logger::STUB_TAG;
1621 break;
1622 case Code::REGEXP:
1623 description = "Regular expression code";
1624 tag = Logger::REG_EXP_TAG;
1625 break;
1626 case Code::BUILTIN:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001627 description = isolate_->builtins()->name(code_object->builtin_index());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001628 tag = Logger::BUILTIN_TAG;
1629 break;
1630 case Code::HANDLER:
1631 description = "An IC handler from the snapshot";
1632 tag = Logger::HANDLER_TAG;
1633 break;
1634 case Code::KEYED_LOAD_IC:
1635 description = "A keyed load IC from the snapshot";
1636 tag = Logger::KEYED_LOAD_IC_TAG;
1637 break;
1638 case Code::LOAD_IC:
1639 description = "A load IC from the snapshot";
1640 tag = Logger::LOAD_IC_TAG;
1641 break;
1642 case Code::CALL_IC:
1643 description = "A call IC from the snapshot";
1644 tag = Logger::CALL_IC_TAG;
1645 break;
1646 case Code::STORE_IC:
1647 description = "A store IC from the snapshot";
1648 tag = Logger::STORE_IC_TAG;
1649 break;
1650 case Code::KEYED_STORE_IC:
1651 description = "A keyed store IC from the snapshot";
1652 tag = Logger::KEYED_STORE_IC_TAG;
1653 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001654 case Code::WASM_FUNCTION:
1655 description = "A wasm function";
1656 tag = Logger::STUB_TAG;
1657 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001658 case Code::NUMBER_OF_KINDS:
1659 break;
Steve Blockd0582a62009-12-15 09:54:21 +00001660 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001661 PROFILE(isolate_, CodeCreateEvent(tag, code_object, description));
Ben Murdochf87a2032010-10-22 12:50:53 +01001662}
1663
1664
Andrei Popescu31002712010-02-23 13:46:05 +00001665void Logger::LogCodeObjects() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001666 Heap* heap = isolate_->heap();
1667 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001668 "Logger::LogCodeObjects");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001669 HeapIterator iterator(heap);
1670 DisallowHeapAllocation no_gc;
Andrei Popescu31002712010-02-23 13:46:05 +00001671 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1672 if (obj->IsCode()) LogCodeObject(obj);
1673 }
1674}
1675
1676
Ben Murdoch589d6972011-11-30 16:04:58 +00001677void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
1678 Handle<Code> code) {
1679 Handle<String> func_name(shared->DebugName());
1680 if (shared->script()->IsScript()) {
1681 Handle<Script> script(Script::cast(shared->script()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001682 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
1683 int column_num =
1684 Script::GetColumnNumber(script, shared->start_position()) + 1;
Ben Murdoch589d6972011-11-30 16:04:58 +00001685 if (script->name()->IsString()) {
1686 Handle<String> script_name(String::cast(script->name()));
Ben Murdoch589d6972011-11-30 16:04:58 +00001687 if (line_num > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001688 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001689 CodeCreateEvent(
1690 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001691 *code, *shared, NULL,
1692 *script_name, line_num, column_num));
Ben Murdoch589d6972011-11-30 16:04:58 +00001693 } else {
1694 // Can't distinguish eval and script here, so always use Script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001695 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001696 CodeCreateEvent(
1697 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001698 *code, *shared, NULL, *script_name));
Ben Murdoch589d6972011-11-30 16:04:58 +00001699 }
1700 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001701 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001702 CodeCreateEvent(
1703 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001704 *code, *shared, NULL,
1705 isolate_->heap()->empty_string(), line_num, column_num));
Ben Murdoch589d6972011-11-30 16:04:58 +00001706 }
1707 } else if (shared->IsApiFunction()) {
1708 // API function.
1709 FunctionTemplateInfo* fun_data = shared->get_api_func_data();
1710 Object* raw_call_data = fun_data->call_code();
1711 if (!raw_call_data->IsUndefined()) {
1712 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1713 Object* callback_obj = call_data->callback();
1714 Address entry_point = v8::ToCData<Address>(callback_obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001715 PROFILE(isolate_, CallbackEvent(*func_name, entry_point));
Ben Murdoch589d6972011-11-30 16:04:58 +00001716 }
1717 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001718 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001719 CodeCreateEvent(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001720 Logger::LAZY_COMPILE_TAG, *code, *shared, NULL, *func_name));
Ben Murdoch589d6972011-11-30 16:04:58 +00001721 }
1722}
1723
1724
Steve Block3ce2e202009-11-05 08:53:23 +00001725void Logger::LogCompiledFunctions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001726 Heap* heap = isolate_->heap();
1727 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001728 "Logger::LogCompiledFunctions");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001729 HandleScope scope(isolate_);
1730 const int compiled_funcs_count = EnumerateCompiledFunctions(heap, NULL, NULL);
Kristian Monsen25f61362010-05-21 11:50:48 +01001731 ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001732 ScopedVector< Handle<Code> > code_objects(compiled_funcs_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001733 EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00001734
1735 // During iteration, there can be heap allocation due to
1736 // GetScriptLineNumber call.
1737 for (int i = 0; i < compiled_funcs_count; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001738 if (code_objects[i].is_identical_to(isolate_->builtins()->CompileLazy()))
Steve Block44f0eee2011-05-26 01:26:41 +01001739 continue;
Ben Murdoch589d6972011-11-30 16:04:58 +00001740 LogExistingFunction(sfis[i], code_objects[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001741 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001742}
1743
Steve Blockd0582a62009-12-15 09:54:21 +00001744
1745void Logger::LogAccessorCallbacks() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001746 Heap* heap = isolate_->heap();
1747 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001748 "Logger::LogAccessorCallbacks");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001749 HeapIterator iterator(heap);
1750 DisallowHeapAllocation no_gc;
Leon Clarked91b9f72010-01-27 17:25:45 +00001751 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001752 if (!obj->IsExecutableAccessorInfo()) continue;
1753 ExecutableAccessorInfo* ai = ExecutableAccessorInfo::cast(obj);
1754 if (!ai->name()->IsName()) continue;
Steve Blockd0582a62009-12-15 09:54:21 +00001755 Address getter_entry = v8::ToCData<Address>(ai->getter());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001756 Name* name = Name::cast(ai->name());
Steve Blockd0582a62009-12-15 09:54:21 +00001757 if (getter_entry != 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001758 PROFILE(isolate_, GetterCallbackEvent(name, getter_entry));
Steve Blockd0582a62009-12-15 09:54:21 +00001759 }
1760 Address setter_entry = v8::ToCData<Address>(ai->setter());
1761 if (setter_entry != 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001762 PROFILE(isolate_, SetterCallbackEvent(name, setter_entry));
Steve Blockd0582a62009-12-15 09:54:21 +00001763 }
1764 }
1765}
1766
Steve Blocka7e24c12009-10-30 11:49:00 +00001767
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001768static void AddIsolateIdIfNeeded(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001769 Isolate* isolate) {
1770 if (FLAG_logfile_per_isolate) os << "isolate-" << isolate << "-";
1771}
1772
1773
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001774static void PrepareLogFileName(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001775 Isolate* isolate, const char* file_name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001776 int dir_separator_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001777 for (const char* p = file_name; *p; p++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001778 if (base::OS::isDirectorySeparator(*p)) dir_separator_count++;
1779 }
1780
1781 for (const char* p = file_name; *p; p++) {
1782 if (dir_separator_count == 0) {
1783 AddIsolateIdIfNeeded(os, isolate);
1784 dir_separator_count--;
1785 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001786 if (*p == '%') {
1787 p++;
1788 switch (*p) {
1789 case '\0':
1790 // If there's a % at the end of the string we back up
1791 // one character so we can escape the loop properly.
1792 p--;
1793 break;
1794 case 'p':
1795 os << base::OS::GetCurrentProcessId();
1796 break;
1797 case 't':
1798 // %t expands to the current time in milliseconds.
1799 os << static_cast<int64_t>(base::OS::TimeCurrentMillis());
1800 break;
1801 case '%':
1802 // %% expands (contracts really) to %.
1803 os << '%';
1804 break;
1805 default:
1806 // All other %'s expand to themselves.
1807 os << '%' << *p;
1808 break;
1809 }
1810 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001811 if (base::OS::isDirectorySeparator(*p)) dir_separator_count--;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001812 os << *p;
1813 }
1814 }
1815}
1816
1817
1818bool Logger::SetUp(Isolate* isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +01001819 // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
1820 if (is_initialized_) return true;
1821 is_initialized_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001822
Ben Murdochf87a2032010-10-22 12:50:53 +01001823 // --ll-prof implies --log-code and --log-snapshot-positions.
1824 if (FLAG_ll_prof) {
Ben Murdochf87a2032010-10-22 12:50:53 +01001825 FLAG_log_snapshot_positions = true;
1826 }
1827
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001828 std::ostringstream log_file_name;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001829 PrepareLogFileName(log_file_name, isolate, FLAG_logfile);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001830 log_->Initialize(log_file_name.str().c_str());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001831
1832
1833 if (FLAG_perf_basic_prof) {
1834 perf_basic_logger_ = new PerfBasicLogger();
1835 addCodeEventListener(perf_basic_logger_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001836 }
1837
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001838 if (FLAG_ll_prof) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001839 ll_logger_ = new LowLevelLogger(log_file_name.str().c_str());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001840 addCodeEventListener(ll_logger_);
1841 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001842
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001843 ticker_ = new Ticker(isolate, kSamplingIntervalMs);
1844
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001845 if (Log::InitLogAtStart()) {
1846 is_logging_ = true;
Steve Block6ded16b2010-05-10 14:33:55 +01001847 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001848
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001849 if (FLAG_log_internal_timer_events || FLAG_prof_cpp) timer_.Start();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001850
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001851 if (FLAG_prof_cpp) {
Steve Block44f0eee2011-05-26 01:26:41 +01001852 profiler_ = new Profiler(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001853 is_logging_ = true;
1854 profiler_->Engage();
Steve Blocka7e24c12009-10-30 11:49:00 +00001855 }
1856
Steve Blocka7e24c12009-10-30 11:49:00 +00001857 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001858}
1859
1860
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001861void Logger::SetCodeEventHandler(uint32_t options,
1862 JitCodeEventHandler event_handler) {
1863 if (jit_logger_) {
1864 removeCodeEventListener(jit_logger_);
1865 delete jit_logger_;
1866 jit_logger_ = NULL;
1867 }
1868
1869 if (event_handler) {
1870 jit_logger_ = new JitLogger(event_handler);
1871 addCodeEventListener(jit_logger_);
1872 if (options & kJitCodeEventEnumExisting) {
1873 HandleScope scope(isolate_);
1874 LogCodeObjects();
1875 LogCompiledFunctions();
1876 }
1877 }
1878}
1879
1880
Steve Block44f0eee2011-05-26 01:26:41 +01001881Sampler* Logger::sampler() {
1882 return ticker_;
1883}
1884
1885
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001886FILE* Logger::TearDown() {
1887 if (!is_initialized_) return NULL;
Steve Block44f0eee2011-05-26 01:26:41 +01001888 is_initialized_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001889
1890 // Stop the profiler before closing the file.
1891 if (profiler_ != NULL) {
1892 profiler_->Disengage();
1893 delete profiler_;
1894 profiler_ = NULL;
1895 }
1896
Steve Blocka7e24c12009-10-30 11:49:00 +00001897 delete ticker_;
1898 ticker_ = NULL;
1899
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001900 if (perf_basic_logger_) {
1901 removeCodeEventListener(perf_basic_logger_);
1902 delete perf_basic_logger_;
1903 perf_basic_logger_ = NULL;
1904 }
1905
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001906 if (ll_logger_) {
1907 removeCodeEventListener(ll_logger_);
1908 delete ll_logger_;
1909 ll_logger_ = NULL;
1910 }
1911
1912 if (jit_logger_) {
1913 removeCodeEventListener(jit_logger_);
1914 delete jit_logger_;
1915 jit_logger_ = NULL;
1916 }
1917
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001918 return log_->Close();
Steve Blocka7e24c12009-10-30 11:49:00 +00001919}
1920
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001921} // namespace internal
1922} // namespace v8