blob: cbdd9dd106024dccf3832fbd9375f15b723a45b8 [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()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100937 TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.External");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000938 DCHECK(isolate->current_vm_state() == JS);
939 isolate->set_current_vm_state(EXTERNAL);
940}
941
942
943void Logger::LeaveExternal(Isolate* isolate) {
944 LOG(isolate, TimerEvent(END, TimerEventExternal::name()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100945 TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.External");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000946 DCHECK(isolate->current_vm_state() == EXTERNAL);
947 isolate->set_current_vm_state(JS);
948}
949
950
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000951template <class TimerEvent>
952void TimerEventScope<TimerEvent>::LogTimerEvent(Logger::StartEnd se) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400953 Logger::CallEventLogger(isolate_, TimerEvent::name(), se,
954 TimerEvent::expose_to_api());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000955}
956
957
958// Instantiate template methods.
959#define V(TimerName, expose) \
960 template void TimerEventScope<TimerEvent##TimerName>::LogTimerEvent( \
961 Logger::StartEnd se);
962TIMER_EVENTS_LIST(V)
963#undef V
964
965
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000966namespace {
967// Emits the source code of a regexp. Used by regexp events.
968void LogRegExpSource(Handle<JSRegExp> regexp, Isolate* isolate,
969 Log::MessageBuilder* msg) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000970 // Prints "/" + re.source + "/" +
971 // (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
Steve Blocka7e24c12009-10-30 11:49:00 +0000972
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000973 Handle<Object> source =
974 Object::GetProperty(isolate, regexp, "source").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000975 if (!source->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 msg->Append("no source");
Steve Blocka7e24c12009-10-30 11:49:00 +0000977 return;
978 }
979
980 switch (regexp->TypeTag()) {
981 case JSRegExp::ATOM:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000982 msg->Append('a');
Steve Blocka7e24c12009-10-30 11:49:00 +0000983 break;
984 default:
985 break;
986 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000987 msg->Append('/');
988 msg->AppendDetailed(*Handle<String>::cast(source), false);
989 msg->Append('/');
Steve Blocka7e24c12009-10-30 11:49:00 +0000990
991 // global flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000992 Handle<Object> global =
993 Object::GetProperty(isolate, regexp, "global").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000994 if (global->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000995 msg->Append('g');
Steve Blocka7e24c12009-10-30 11:49:00 +0000996 }
997 // ignorecase flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000998 Handle<Object> ignorecase =
999 Object::GetProperty(isolate, regexp, "ignoreCase").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001000 if (ignorecase->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 msg->Append('i');
Steve Blocka7e24c12009-10-30 11:49:00 +00001002 }
1003 // multiline flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001004 Handle<Object> multiline =
1005 Object::GetProperty(isolate, regexp, "multiline").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001006 if (multiline->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001007 msg->Append('m');
Steve Blocka7e24c12009-10-30 11:49:00 +00001008 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001009}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001010} // namespace
Steve Blocka7e24c12009-10-30 11:49:00 +00001011
1012
1013void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
Steve Block44f0eee2011-05-26 01:26:41 +01001014 if (!log_->IsEnabled() || !FLAG_log_regexp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001015 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001016 msg.Append("regexp-compile,");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001017 LogRegExpSource(regexp, isolate_, &msg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001018 msg.Append(in_cache ? ",hit" : ",miss");
Steve Blocka7e24c12009-10-30 11:49:00 +00001019 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001020}
1021
1022
Steve Blocka7e24c12009-10-30 11:49:00 +00001023void Logger::ApiNamedPropertyAccess(const char* tag,
1024 JSObject* holder,
1025 Object* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001026 DCHECK(name->IsName());
Steve Block44f0eee2011-05-26 01:26:41 +01001027 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001028 String* class_name_obj = holder->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001029 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +00001030 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001031 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001032 base::SmartArrayPointer<char> property_name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001033 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1034 ApiEvent("api,%s,\"%s\",\"%s\"", tag, class_name.get(),
1035 property_name.get());
1036 } else {
1037 Symbol* symbol = Symbol::cast(name);
1038 uint32_t hash = symbol->Hash();
1039 if (symbol->name()->IsUndefined()) {
1040 ApiEvent("api,%s,\"%s\",symbol(hash %x)", tag, class_name.get(), hash);
1041 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001042 base::SmartArrayPointer<char> str =
1043 String::cast(symbol->name())
1044 ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001045 ApiEvent("api,%s,\"%s\",symbol(\"%s\" hash %x)", tag, class_name.get(),
1046 str.get(), hash);
1047 }
1048 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001049}
1050
1051void Logger::ApiIndexedPropertyAccess(const char* tag,
1052 JSObject* holder,
1053 uint32_t index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001054 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001055 String* class_name_obj = holder->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001056 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +00001057 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001058 ApiEvent("api,%s,\"%s\",%u", tag, class_name.get(), index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001059}
1060
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001061
Steve Blocka7e24c12009-10-30 11:49:00 +00001062void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
Steve Block44f0eee2011-05-26 01:26:41 +01001063 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001064 String* class_name_obj = object->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001065 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +00001066 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001067 ApiEvent("api,%s,\"%s\"", tag, class_name.get());
Steve Blocka7e24c12009-10-30 11:49:00 +00001068}
1069
1070
1071void Logger::ApiEntryCall(const char* name) {
Steve Block44f0eee2011-05-26 01:26:41 +01001072 if (!log_->IsEnabled() || !FLAG_log_api) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001073 ApiEvent("api,%s", name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001074}
1075
1076
1077void Logger::NewEvent(const char* name, void* object, size_t size) {
Steve Block44f0eee2011-05-26 01:26:41 +01001078 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001079 Log::MessageBuilder msg(log_);
1080 msg.Append("new,%s,0x%" V8PRIxPTR ",%u", name, object,
Steve Blocka7e24c12009-10-30 11:49:00 +00001081 static_cast<unsigned int>(size));
1082 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001083}
1084
1085
1086void Logger::DeleteEvent(const char* name, void* object) {
Steve Block44f0eee2011-05-26 01:26:41 +01001087 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001088 Log::MessageBuilder msg(log_);
1089 msg.Append("delete,%s,0x%" V8PRIxPTR, name, object);
Steve Blocka7e24c12009-10-30 11:49:00 +00001090 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001091}
1092
1093
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001094void Logger::CallbackEventInternal(const char* prefix, Name* name,
Steve Blockd0582a62009-12-15 09:54:21 +00001095 Address entry_point) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001096 if (!FLAG_log_code || !log_->IsEnabled()) return;
1097 Log::MessageBuilder msg(log_);
1098 msg.Append("%s,%s,-2,",
Ben Murdochb0fe1622011-05-05 13:52:32 +01001099 kLogEventsNames[CODE_CREATION_EVENT],
1100 kLogEventsNames[CALLBACK_TAG]);
Steve Blockd0582a62009-12-15 09:54:21 +00001101 msg.AppendAddress(entry_point);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001103 base::SmartArrayPointer<char> str =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001104 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1105 msg.Append(",1,\"%s%s\"", prefix, str.get());
1106 } else {
1107 Symbol* symbol = Symbol::cast(name);
1108 if (symbol->name()->IsUndefined()) {
1109 msg.Append(",1,symbol(hash %x)", prefix, symbol->Hash());
1110 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001111 base::SmartArrayPointer<char> str =
1112 String::cast(symbol->name())
1113 ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001114 msg.Append(",1,symbol(\"%s\" hash %x)", prefix, str.get(),
1115 symbol->Hash());
1116 }
1117 }
Steve Blockd0582a62009-12-15 09:54:21 +00001118 msg.WriteToLogFile();
1119}
Steve Blockd0582a62009-12-15 09:54:21 +00001120
1121
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001122void Logger::CallbackEvent(Name* name, Address entry_point) {
1123 PROFILER_LOG(CallbackEvent(name, entry_point));
1124 CallbackEventInternal("", name, entry_point);
Steve Blockd0582a62009-12-15 09:54:21 +00001125}
1126
1127
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001128void Logger::GetterCallbackEvent(Name* name, Address entry_point) {
1129 PROFILER_LOG(GetterCallbackEvent(name, entry_point));
1130 CallbackEventInternal("get ", name, entry_point);
Steve Blockd0582a62009-12-15 09:54:21 +00001131}
1132
1133
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001134void Logger::SetterCallbackEvent(Name* name, Address entry_point) {
1135 PROFILER_LOG(SetterCallbackEvent(name, entry_point));
1136 CallbackEventInternal("set ", name, entry_point);
1137}
1138
1139
1140static void AppendCodeCreateHeader(Log::MessageBuilder* msg,
1141 Logger::LogEventsAndTags tag,
1142 Code* code) {
1143 DCHECK(msg);
1144 msg->Append("%s,%s,%d,",
1145 kLogEventsNames[Logger::CODE_CREATION_EVENT],
1146 kLogEventsNames[tag],
1147 code->kind());
1148 msg->AppendAddress(code->address());
1149 msg->Append(",%d,", code->ExecutableSize());
Steve Blockd0582a62009-12-15 09:54:21 +00001150}
1151
1152
Steve Blocka7e24c12009-10-30 11:49:00 +00001153void Logger::CodeCreateEvent(LogEventsAndTags tag,
1154 Code* code,
1155 const char* comment) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001156 PROFILER_LOG(CodeCreateEvent(tag, code, comment));
1157
1158 if (!is_logging_code_events()) return;
1159 CALL_LISTENERS(CodeCreateEvent(tag, code, comment));
1160
1161 if (!FLAG_log_code || !log_->IsEnabled()) return;
1162 Log::MessageBuilder msg(log_);
1163 AppendCodeCreateHeader(&msg, tag, code);
1164 msg.AppendDoubleQuotedString(comment);
Steve Blocka7e24c12009-10-30 11:49:00 +00001165 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001166}
1167
1168
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001169void Logger::CodeCreateEvent(LogEventsAndTags tag,
1170 Code* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001171 Name* name) {
1172 PROFILER_LOG(CodeCreateEvent(tag, code, name));
1173
1174 if (!is_logging_code_events()) return;
1175 CALL_LISTENERS(CodeCreateEvent(tag, code, name));
1176
1177 if (!FLAG_log_code || !log_->IsEnabled()) return;
1178 Log::MessageBuilder msg(log_);
1179 AppendCodeCreateHeader(&msg, tag, code);
1180 if (name->IsString()) {
1181 msg.Append('"');
1182 msg.AppendDetailed(String::cast(name), false);
1183 msg.Append('"');
1184 } else {
1185 msg.AppendSymbolName(Symbol::cast(name));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001186 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001187 msg.WriteToLogFile();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001188}
1189
1190
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001191void Logger::CodeCreateEvent(LogEventsAndTags tag,
1192 Code* code,
1193 SharedFunctionInfo* shared,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001194 CompilationInfo* info,
1195 Name* name) {
1196 PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, name));
Steve Block44f0eee2011-05-26 01:26:41 +01001197
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001198 if (!is_logging_code_events()) return;
1199 CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, name));
1200
1201 if (!FLAG_log_code || !log_->IsEnabled()) return;
1202 if (code == isolate_->builtins()->builtin(Builtins::kCompileLazy)) return;
1203
1204 Log::MessageBuilder msg(log_);
1205 AppendCodeCreateHeader(&msg, tag, code);
1206 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001207 base::SmartArrayPointer<char> str =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001208 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1209 msg.Append("\"%s\"", str.get());
1210 } else {
1211 msg.AppendSymbolName(Symbol::cast(name));
1212 }
1213 msg.Append(',');
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001214 msg.AppendAddress(shared->address());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001215 msg.Append(",%s", ComputeMarker(shared, code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001216 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001217}
1218
1219
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001220// Although, it is possible to extract source and line from
1221// the SharedFunctionInfo object, we left it to caller
1222// to leave logging functions free from heap allocations.
Steve Blocka7e24c12009-10-30 11:49:00 +00001223void Logger::CodeCreateEvent(LogEventsAndTags tag,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001224 Code* code,
1225 SharedFunctionInfo* shared,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001226 CompilationInfo* info,
1227 Name* source, int line, int column) {
1228 PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, source, line, column));
1229
1230 if (!is_logging_code_events()) return;
1231 CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, source, line,
1232 column));
1233
1234 if (!FLAG_log_code || !log_->IsEnabled()) return;
1235 Log::MessageBuilder msg(log_);
1236 AppendCodeCreateHeader(&msg, tag, code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001237 base::SmartArrayPointer<char> name =
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001238 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001239 msg.Append("\"%s ", name.get());
1240 if (source->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001241 base::SmartArrayPointer<char> sourcestr = String::cast(source)->ToCString(
1242 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001243 msg.Append("%s", sourcestr.get());
1244 } else {
1245 msg.AppendSymbolName(Symbol::cast(source));
1246 }
1247 msg.Append(":%d:%d\",", line, column);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001248 msg.AppendAddress(shared->address());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001249 msg.Append(",%s", ComputeMarker(shared, code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001250 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001251}
1252
1253
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001254void Logger::CodeCreateEvent(LogEventsAndTags tag,
1255 Code* code,
1256 int args_count) {
1257 PROFILER_LOG(CodeCreateEvent(tag, code, args_count));
1258
1259 if (!is_logging_code_events()) return;
1260 CALL_LISTENERS(CodeCreateEvent(tag, code, args_count));
1261
1262 if (!FLAG_log_code || !log_->IsEnabled()) return;
1263 Log::MessageBuilder msg(log_);
1264 AppendCodeCreateHeader(&msg, tag, code);
1265 msg.Append("\"args_count: %d\"", args_count);
1266 msg.WriteToLogFile();
1267}
1268
1269
1270void Logger::CodeDisableOptEvent(Code* code,
1271 SharedFunctionInfo* shared) {
1272 PROFILER_LOG(CodeDisableOptEvent(code, shared));
1273
1274 if (!is_logging_code_events()) return;
1275 CALL_LISTENERS(CodeDisableOptEvent(code, shared));
1276
1277 if (!FLAG_log_code || !log_->IsEnabled()) return;
1278 Log::MessageBuilder msg(log_);
1279 msg.Append("%s,", kLogEventsNames[CODE_DISABLE_OPT_EVENT]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001280 base::SmartArrayPointer<char> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001281 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1282 msg.Append("\"%s\",", name.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001283 msg.Append("\"%s\"", GetBailoutReason(shared->disable_optimization_reason()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001284 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001285}
1286
1287
Ben Murdochf87a2032010-10-22 12:50:53 +01001288void Logger::CodeMovingGCEvent() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 PROFILER_LOG(CodeMovingGCEvent());
1290
1291 if (!is_logging_code_events()) return;
Ben Murdoch257744e2011-11-30 15:57:28 +00001292 if (!log_->IsEnabled() || !FLAG_ll_prof) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001293 CALL_LISTENERS(CodeMovingGCEvent());
1294 base::OS::SignalCodeMovingGC();
Ben Murdochf87a2032010-10-22 12:50:53 +01001295}
1296
1297
Steve Blocka7e24c12009-10-30 11:49:00 +00001298void Logger::RegExpCodeCreateEvent(Code* code, String* source) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001299 PROFILER_LOG(RegExpCodeCreateEvent(code, source));
1300
1301 if (!is_logging_code_events()) return;
1302 CALL_LISTENERS(RegExpCodeCreateEvent(code, source));
1303
1304 if (!FLAG_log_code || !log_->IsEnabled()) return;
1305 Log::MessageBuilder msg(log_);
1306 AppendCodeCreateHeader(&msg, REG_EXP_TAG, code);
1307 msg.Append('"');
Steve Blocka7e24c12009-10-30 11:49:00 +00001308 msg.AppendDetailed(source, false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001309 msg.Append('"');
Steve Blocka7e24c12009-10-30 11:49:00 +00001310 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001311}
1312
1313
1314void Logger::CodeMoveEvent(Address from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001315 PROFILER_LOG(CodeMoveEvent(from, to));
1316
1317 if (!is_logging_code_events()) return;
1318 CALL_LISTENERS(CodeMoveEvent(from, to));
Leon Clarked91b9f72010-01-27 17:25:45 +00001319 MoveEventInternal(CODE_MOVE_EVENT, from, to);
Steve Blocka7e24c12009-10-30 11:49:00 +00001320}
1321
1322
1323void Logger::CodeDeleteEvent(Address from) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001324 PROFILER_LOG(CodeDeleteEvent(from));
1325
1326 if (!is_logging_code_events()) return;
1327 CALL_LISTENERS(CodeDeleteEvent(from));
1328
1329 if (!FLAG_log_code || !log_->IsEnabled()) return;
1330 Log::MessageBuilder msg(log_);
1331 msg.Append("%s,", kLogEventsNames[CODE_DELETE_EVENT]);
1332 msg.AppendAddress(from);
1333 msg.WriteToLogFile();
1334}
1335
1336
1337void Logger::CodeLinePosInfoAddPositionEvent(void* jit_handler_data,
1338 int pc_offset,
1339 int position) {
1340 JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1341 pc_offset,
1342 position,
1343 JitCodeEvent::POSITION));
1344}
1345
1346
1347void Logger::CodeLinePosInfoAddStatementPositionEvent(void* jit_handler_data,
1348 int pc_offset,
1349 int position) {
1350 JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1351 pc_offset,
1352 position,
1353 JitCodeEvent::STATEMENT_POSITION));
1354}
1355
1356
1357void Logger::CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder) {
1358 if (jit_logger_ != NULL) {
1359 pos_recorder->AttachJITHandlerData(jit_logger_->StartCodePosInfoEvent());
Ben Murdoch257744e2011-11-30 15:57:28 +00001360 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001361}
1362
1363
1364void Logger::CodeEndLinePosInfoRecordEvent(Code* code,
1365 void* jit_handler_data) {
1366 JIT_LOG(EndCodePosInfoEvent(code, jit_handler_data));
1367}
1368
1369
1370void Logger::CodeNameEvent(Address addr, int pos, const char* code_name) {
1371 if (code_name == NULL) return; // Not a code object.
1372 Log::MessageBuilder msg(log_);
1373 msg.Append("%s,%d,", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
1374 msg.AppendDoubleQuotedString(code_name);
1375 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001376}
1377
1378
Leon Clarkee46be812010-01-19 14:06:41 +00001379void Logger::SnapshotPositionEvent(Address addr, int pos) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001380 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001381 LL_LOG(SnapshotPositionEvent(addr, pos));
Ben Murdoch257744e2011-11-30 15:57:28 +00001382 if (!FLAG_log_snapshot_positions) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001383 Log::MessageBuilder msg(log_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001384 msg.Append("%s,", kLogEventsNames[SNAPSHOT_POSITION_EVENT]);
Leon Clarkee46be812010-01-19 14:06:41 +00001385 msg.AppendAddress(addr);
1386 msg.Append(",%d", pos);
Leon Clarkee46be812010-01-19 14:06:41 +00001387 msg.WriteToLogFile();
Leon Clarkee46be812010-01-19 14:06:41 +00001388}
1389
1390
Steve Block44f0eee2011-05-26 01:26:41 +01001391void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392 if (!is_logging_code_events()) return;
Steve Block44f0eee2011-05-26 01:26:41 +01001393 MoveEventInternal(SHARED_FUNC_MOVE_EVENT, from, to);
Leon Clarked91b9f72010-01-27 17:25:45 +00001394}
1395
1396
Leon Clarked91b9f72010-01-27 17:25:45 +00001397void Logger::MoveEventInternal(LogEventsAndTags event,
1398 Address from,
1399 Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001400 if (!FLAG_log_code || !log_->IsEnabled()) return;
1401 Log::MessageBuilder msg(log_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001402 msg.Append("%s,", kLogEventsNames[event]);
Leon Clarked91b9f72010-01-27 17:25:45 +00001403 msg.AppendAddress(from);
1404 msg.Append(',');
Ben Murdochb0fe1622011-05-05 13:52:32 +01001405 msg.AppendAddress(to);
Leon Clarked91b9f72010-01-27 17:25:45 +00001406 msg.WriteToLogFile();
1407}
Leon Clarked91b9f72010-01-27 17:25:45 +00001408
1409
Steve Blocka7e24c12009-10-30 11:49:00 +00001410void Logger::ResourceEvent(const char* name, const char* tag) {
Steve Block44f0eee2011-05-26 01:26:41 +01001411 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001412 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001413 msg.Append("%s,%s,", name, tag);
1414
1415 uint32_t sec, usec;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001416 if (base::OS::GetUserTime(&sec, &usec) != -1) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001417 msg.Append("%d,%d,", sec, usec);
1418 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001419 msg.Append("%.0f", base::OS::TimeCurrentMillis());
Steve Blocka7e24c12009-10-30 11:49:00 +00001420 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001421}
1422
1423
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001424void Logger::SuspectReadEvent(Name* name, Object* obj) {
Steve Block44f0eee2011-05-26 01:26:41 +01001425 if (!log_->IsEnabled() || !FLAG_log_suspect) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001426 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001427 String* class_name = obj->IsJSObject()
1428 ? JSObject::cast(obj)->class_name()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001429 : isolate_->heap()->empty_string();
Steve Blocka7e24c12009-10-30 11:49:00 +00001430 msg.Append("suspect-read,");
1431 msg.Append(class_name);
1432 msg.Append(',');
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001433 if (name->IsString()) {
1434 msg.Append('"');
1435 msg.Append(String::cast(name));
1436 msg.Append('"');
1437 } else {
1438 msg.AppendSymbolName(Symbol::cast(name));
1439 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001440 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001441}
1442
1443
1444void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
Steve Block44f0eee2011-05-26 01:26:41 +01001445 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001446 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001447 // Using non-relative system time in order to be able to synchronize with
1448 // external memory profiling events (e.g. DOM memory size).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001449 msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f", space, kind,
1450 base::OS::TimeCurrentMillis());
Steve Blocka7e24c12009-10-30 11:49:00 +00001451 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001452}
1453
1454
1455void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
Steve Block44f0eee2011-05-26 01:26:41 +01001456 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001457 Log::MessageBuilder msg(log_);
1458 msg.Append("heap-sample-end,\"%s\",\"%s\"", space, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001459 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001460}
1461
1462
1463void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
Steve Block44f0eee2011-05-26 01:26:41 +01001464 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001465 Log::MessageBuilder msg(log_);
1466 msg.Append("heap-sample-item,%s,%d,%d", type, number, bytes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001467 msg.WriteToLogFile();
Steve Block3ce2e202009-11-05 08:53:23 +00001468}
1469
1470
Steve Blocka7e24c12009-10-30 11:49:00 +00001471void Logger::DebugTag(const char* call_site_tag) {
Steve Block44f0eee2011-05-26 01:26:41 +01001472 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001473 Log::MessageBuilder msg(log_);
1474 msg.Append("debug-tag,%s", call_site_tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001475 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001476}
1477
1478
1479void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
Steve Block44f0eee2011-05-26 01:26:41 +01001480 if (!log_->IsEnabled() || !FLAG_log) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001481 StringBuilder s(parameter.length() + 1);
1482 for (int i = 0; i < parameter.length(); ++i) {
1483 s.AddCharacter(static_cast<char>(parameter[i]));
1484 }
1485 char* parameter_string = s.Finalize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001486 Log::MessageBuilder msg(log_);
1487 msg.Append("debug-queue-event,%s,%15.3f,%s", event_type,
1488 base::OS::TimeCurrentMillis(), parameter_string);
Steve Blocka7e24c12009-10-30 11:49:00 +00001489 DeleteArray(parameter_string);
1490 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001491}
1492
1493
Steve Blocka7e24c12009-10-30 11:49:00 +00001494void Logger::TickEvent(TickSample* sample, bool overflow) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001495 if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001496 Log::MessageBuilder msg(log_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001497 msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
1498 msg.AppendAddress(sample->pc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001499 msg.Append(",%ld", static_cast<int>(timer_.Elapsed().InMicroseconds()));
Steve Block44f0eee2011-05-26 01:26:41 +01001500 if (sample->has_external_callback) {
1501 msg.Append(",1,");
Ben Murdoch097c5b22016-05-18 11:27:45 +01001502 msg.AppendAddress(sample->external_callback_entry);
Steve Block44f0eee2011-05-26 01:26:41 +01001503 } else {
1504 msg.Append(",0,");
1505 msg.AppendAddress(sample->tos);
1506 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001507 msg.Append(",%d", static_cast<int>(sample->state));
1508 if (overflow) {
1509 msg.Append(",overflow");
1510 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001511 for (unsigned i = 0; i < sample->frames_count; ++i) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001512 msg.Append(',');
Ben Murdochb0fe1622011-05-05 13:52:32 +01001513 msg.AppendAddress(sample->stack[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001514 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001515 msg.WriteToLogFile();
1516}
1517
1518
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001519void Logger::StopProfiler() {
Steve Block44f0eee2011-05-26 01:26:41 +01001520 if (!log_->IsEnabled()) return;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001521 if (profiler_ != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001522 profiler_->pause();
1523 is_logging_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001524 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001525}
1526
1527
1528// This function can be called when Log's mutex is acquired,
1529// either from main or Profiler's thread.
Steve Block44f0eee2011-05-26 01:26:41 +01001530void Logger::LogFailure() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001531 StopProfiler();
Steve Blocka7e24c12009-10-30 11:49:00 +00001532}
1533
1534
Ben Murdochb0fe1622011-05-05 13:52:32 +01001535class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor {
1536 public:
1537 EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis,
1538 Handle<Code>* code_objects,
1539 int* count)
1540 : sfis_(sfis), code_objects_(code_objects), count_(count) { }
1541
1542 virtual void EnterContext(Context* context) {}
1543 virtual void LeaveContext(Context* context) {}
1544
1545 virtual void VisitFunction(JSFunction* function) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001546 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(function->shared());
1547 Object* maybe_script = sfi->script();
1548 if (maybe_script->IsScript()
1549 && !Script::cast(maybe_script)->HasValidSource()) return;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001550 if (sfis_ != NULL) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001551 sfis_[*count_] = Handle<SharedFunctionInfo>(sfi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001552 }
1553 if (code_objects_ != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001554 DCHECK(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001555 code_objects_[*count_] = Handle<Code>(function->code());
1556 }
1557 *count_ = *count_ + 1;
1558 }
1559
1560 private:
1561 Handle<SharedFunctionInfo>* sfis_;
1562 Handle<Code>* code_objects_;
1563 int* count_;
1564};
1565
1566
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001567static int EnumerateCompiledFunctions(Heap* heap,
1568 Handle<SharedFunctionInfo>* sfis,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001569 Handle<Code>* code_objects) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001570 HeapIterator iterator(heap);
1571 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001572 int compiled_funcs_count = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001573
1574 // Iterate the heap to find shared function info objects and record
1575 // the unoptimized code for them.
Leon Clarked91b9f72010-01-27 17:25:45 +00001576 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001577 if (!obj->IsSharedFunctionInfo()) continue;
1578 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
1579 if (sfi->is_compiled()
1580 && (!sfi->script()->IsScript()
1581 || Script::cast(sfi->script())->HasValidSource())) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001582 if (sfis != NULL) {
Steve Block3ce2e202009-11-05 08:53:23 +00001583 sfis[compiled_funcs_count] = Handle<SharedFunctionInfo>(sfi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001584 }
1585 if (code_objects != NULL) {
1586 code_objects[compiled_funcs_count] = Handle<Code>(sfi->code());
1587 }
Steve Block3ce2e202009-11-05 08:53:23 +00001588 ++compiled_funcs_count;
Steve Blocka7e24c12009-10-30 11:49:00 +00001589 }
1590 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001591
1592 // Iterate all optimized functions in all contexts.
1593 EnumerateOptimizedFunctionsVisitor visitor(sfis,
1594 code_objects,
1595 &compiled_funcs_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001596 Deoptimizer::VisitAllOptimizedFunctions(heap->isolate(), &visitor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001597
Steve Block3ce2e202009-11-05 08:53:23 +00001598 return compiled_funcs_count;
1599}
1600
1601
Steve Blockd0582a62009-12-15 09:54:21 +00001602void Logger::LogCodeObject(Object* object) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001603 Code* code_object = Code::cast(object);
1604 LogEventsAndTags tag = Logger::STUB_TAG;
1605 const char* description = "Unknown code from the snapshot";
1606 switch (code_object->kind()) {
1607 case Code::FUNCTION:
1608 case Code::OPTIMIZED_FUNCTION:
1609 return; // We log this later using LogCompiledFunctions.
1610 case Code::BINARY_OP_IC:
1611 case Code::COMPARE_IC: // fall through
1612 case Code::COMPARE_NIL_IC: // fall through
1613 case Code::TO_BOOLEAN_IC: // fall through
1614 case Code::STUB:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001615 description = CodeStub::MajorName(CodeStub::GetMajorKey(code_object));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001616 if (description == NULL)
1617 description = "A stub from the snapshot";
1618 tag = Logger::STUB_TAG;
1619 break;
1620 case Code::REGEXP:
1621 description = "Regular expression code";
1622 tag = Logger::REG_EXP_TAG;
1623 break;
1624 case Code::BUILTIN:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001625 description = isolate_->builtins()->name(code_object->builtin_index());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001626 tag = Logger::BUILTIN_TAG;
1627 break;
1628 case Code::HANDLER:
1629 description = "An IC handler from the snapshot";
1630 tag = Logger::HANDLER_TAG;
1631 break;
1632 case Code::KEYED_LOAD_IC:
1633 description = "A keyed load IC from the snapshot";
1634 tag = Logger::KEYED_LOAD_IC_TAG;
1635 break;
1636 case Code::LOAD_IC:
1637 description = "A load IC from the snapshot";
1638 tag = Logger::LOAD_IC_TAG;
1639 break;
1640 case Code::CALL_IC:
1641 description = "A call IC from the snapshot";
1642 tag = Logger::CALL_IC_TAG;
1643 break;
1644 case Code::STORE_IC:
1645 description = "A store IC from the snapshot";
1646 tag = Logger::STORE_IC_TAG;
1647 break;
1648 case Code::KEYED_STORE_IC:
1649 description = "A keyed store IC from the snapshot";
1650 tag = Logger::KEYED_STORE_IC_TAG;
1651 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001652 case Code::WASM_FUNCTION:
1653 description = "A wasm function";
1654 tag = Logger::STUB_TAG;
1655 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001656 case Code::NUMBER_OF_KINDS:
1657 break;
Steve Blockd0582a62009-12-15 09:54:21 +00001658 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001659 PROFILE(isolate_, CodeCreateEvent(tag, code_object, description));
Ben Murdochf87a2032010-10-22 12:50:53 +01001660}
1661
1662
Andrei Popescu31002712010-02-23 13:46:05 +00001663void Logger::LogCodeObjects() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001664 Heap* heap = isolate_->heap();
1665 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001666 "Logger::LogCodeObjects");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001667 HeapIterator iterator(heap);
1668 DisallowHeapAllocation no_gc;
Andrei Popescu31002712010-02-23 13:46:05 +00001669 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1670 if (obj->IsCode()) LogCodeObject(obj);
1671 }
1672}
1673
1674
Ben Murdoch589d6972011-11-30 16:04:58 +00001675void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
1676 Handle<Code> code) {
1677 Handle<String> func_name(shared->DebugName());
1678 if (shared->script()->IsScript()) {
1679 Handle<Script> script(Script::cast(shared->script()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001680 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
1681 int column_num =
1682 Script::GetColumnNumber(script, shared->start_position()) + 1;
Ben Murdoch589d6972011-11-30 16:04:58 +00001683 if (script->name()->IsString()) {
1684 Handle<String> script_name(String::cast(script->name()));
Ben Murdoch589d6972011-11-30 16:04:58 +00001685 if (line_num > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001686 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001687 CodeCreateEvent(
1688 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001689 *code, *shared, NULL,
1690 *script_name, line_num, column_num));
Ben Murdoch589d6972011-11-30 16:04:58 +00001691 } else {
1692 // Can't distinguish eval and script here, so always use Script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001693 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001694 CodeCreateEvent(
1695 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001696 *code, *shared, NULL, *script_name));
Ben Murdoch589d6972011-11-30 16:04:58 +00001697 }
1698 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001699 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001700 CodeCreateEvent(
1701 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001702 *code, *shared, NULL,
1703 isolate_->heap()->empty_string(), line_num, column_num));
Ben Murdoch589d6972011-11-30 16:04:58 +00001704 }
1705 } else if (shared->IsApiFunction()) {
1706 // API function.
1707 FunctionTemplateInfo* fun_data = shared->get_api_func_data();
1708 Object* raw_call_data = fun_data->call_code();
1709 if (!raw_call_data->IsUndefined()) {
1710 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1711 Object* callback_obj = call_data->callback();
1712 Address entry_point = v8::ToCData<Address>(callback_obj);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001713#if USES_FUNCTION_DESCRIPTORS
1714 entry_point = *FUNCTION_ENTRYPOINT_ADDRESS(entry_point);
1715#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001716 PROFILE(isolate_, CallbackEvent(*func_name, entry_point));
Ben Murdoch589d6972011-11-30 16:04:58 +00001717 }
1718 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001719 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001720 CodeCreateEvent(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001721 Logger::LAZY_COMPILE_TAG, *code, *shared, NULL, *func_name));
Ben Murdoch589d6972011-11-30 16:04:58 +00001722 }
1723}
1724
1725
Steve Block3ce2e202009-11-05 08:53:23 +00001726void Logger::LogCompiledFunctions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001727 Heap* heap = isolate_->heap();
1728 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001729 "Logger::LogCompiledFunctions");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001730 HandleScope scope(isolate_);
1731 const int compiled_funcs_count = EnumerateCompiledFunctions(heap, NULL, NULL);
Kristian Monsen25f61362010-05-21 11:50:48 +01001732 ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001733 ScopedVector< Handle<Code> > code_objects(compiled_funcs_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001734 EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00001735
1736 // During iteration, there can be heap allocation due to
1737 // GetScriptLineNumber call.
1738 for (int i = 0; i < compiled_funcs_count; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001739 if (code_objects[i].is_identical_to(isolate_->builtins()->CompileLazy()))
Steve Block44f0eee2011-05-26 01:26:41 +01001740 continue;
Ben Murdoch589d6972011-11-30 16:04:58 +00001741 LogExistingFunction(sfis[i], code_objects[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001742 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001743}
1744
Steve Blockd0582a62009-12-15 09:54:21 +00001745
1746void Logger::LogAccessorCallbacks() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001747 Heap* heap = isolate_->heap();
1748 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001749 "Logger::LogAccessorCallbacks");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001750 HeapIterator iterator(heap);
1751 DisallowHeapAllocation no_gc;
Leon Clarked91b9f72010-01-27 17:25:45 +00001752 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001753 if (!obj->IsAccessorInfo()) continue;
1754 AccessorInfo* ai = AccessorInfo::cast(obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001755 if (!ai->name()->IsName()) continue;
Steve Blockd0582a62009-12-15 09:54:21 +00001756 Address getter_entry = v8::ToCData<Address>(ai->getter());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001757 Name* name = Name::cast(ai->name());
Steve Blockd0582a62009-12-15 09:54:21 +00001758 if (getter_entry != 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001759#if USES_FUNCTION_DESCRIPTORS
1760 getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(getter_entry);
1761#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001762 PROFILE(isolate_, GetterCallbackEvent(name, getter_entry));
Steve Blockd0582a62009-12-15 09:54:21 +00001763 }
1764 Address setter_entry = v8::ToCData<Address>(ai->setter());
1765 if (setter_entry != 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001766#if USES_FUNCTION_DESCRIPTORS
1767 setter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(setter_entry);
1768#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001769 PROFILE(isolate_, SetterCallbackEvent(name, setter_entry));
Steve Blockd0582a62009-12-15 09:54:21 +00001770 }
1771 }
1772}
1773
Steve Blocka7e24c12009-10-30 11:49:00 +00001774
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001775static void AddIsolateIdIfNeeded(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001776 Isolate* isolate) {
1777 if (FLAG_logfile_per_isolate) os << "isolate-" << isolate << "-";
1778}
1779
1780
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001781static void PrepareLogFileName(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001782 Isolate* isolate, const char* file_name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001783 int dir_separator_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001784 for (const char* p = file_name; *p; p++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001785 if (base::OS::isDirectorySeparator(*p)) dir_separator_count++;
1786 }
1787
1788 for (const char* p = file_name; *p; p++) {
1789 if (dir_separator_count == 0) {
1790 AddIsolateIdIfNeeded(os, isolate);
1791 dir_separator_count--;
1792 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001793 if (*p == '%') {
1794 p++;
1795 switch (*p) {
1796 case '\0':
1797 // If there's a % at the end of the string we back up
1798 // one character so we can escape the loop properly.
1799 p--;
1800 break;
1801 case 'p':
1802 os << base::OS::GetCurrentProcessId();
1803 break;
1804 case 't':
1805 // %t expands to the current time in milliseconds.
1806 os << static_cast<int64_t>(base::OS::TimeCurrentMillis());
1807 break;
1808 case '%':
1809 // %% expands (contracts really) to %.
1810 os << '%';
1811 break;
1812 default:
1813 // All other %'s expand to themselves.
1814 os << '%' << *p;
1815 break;
1816 }
1817 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001818 if (base::OS::isDirectorySeparator(*p)) dir_separator_count--;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001819 os << *p;
1820 }
1821 }
1822}
1823
1824
1825bool Logger::SetUp(Isolate* isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +01001826 // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
1827 if (is_initialized_) return true;
1828 is_initialized_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001829
Ben Murdochf87a2032010-10-22 12:50:53 +01001830 // --ll-prof implies --log-code and --log-snapshot-positions.
1831 if (FLAG_ll_prof) {
Ben Murdochf87a2032010-10-22 12:50:53 +01001832 FLAG_log_snapshot_positions = true;
1833 }
1834
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001835 std::ostringstream log_file_name;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001836 PrepareLogFileName(log_file_name, isolate, FLAG_logfile);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001837 log_->Initialize(log_file_name.str().c_str());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001838
1839
1840 if (FLAG_perf_basic_prof) {
1841 perf_basic_logger_ = new PerfBasicLogger();
1842 addCodeEventListener(perf_basic_logger_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001843 }
1844
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001845 if (FLAG_ll_prof) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001846 ll_logger_ = new LowLevelLogger(log_file_name.str().c_str());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001847 addCodeEventListener(ll_logger_);
1848 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001849
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001850 ticker_ = new Ticker(isolate, kSamplingIntervalMs);
1851
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001852 if (Log::InitLogAtStart()) {
1853 is_logging_ = true;
Steve Block6ded16b2010-05-10 14:33:55 +01001854 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001855
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001856 if (FLAG_log_internal_timer_events || FLAG_prof_cpp) timer_.Start();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001857
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001858 if (FLAG_prof_cpp) {
Steve Block44f0eee2011-05-26 01:26:41 +01001859 profiler_ = new Profiler(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001860 is_logging_ = true;
1861 profiler_->Engage();
Steve Blocka7e24c12009-10-30 11:49:00 +00001862 }
1863
Steve Blocka7e24c12009-10-30 11:49:00 +00001864 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001865}
1866
1867
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001868void Logger::SetCodeEventHandler(uint32_t options,
1869 JitCodeEventHandler event_handler) {
1870 if (jit_logger_) {
1871 removeCodeEventListener(jit_logger_);
1872 delete jit_logger_;
1873 jit_logger_ = NULL;
1874 }
1875
1876 if (event_handler) {
1877 jit_logger_ = new JitLogger(event_handler);
1878 addCodeEventListener(jit_logger_);
1879 if (options & kJitCodeEventEnumExisting) {
1880 HandleScope scope(isolate_);
1881 LogCodeObjects();
1882 LogCompiledFunctions();
1883 }
1884 }
1885}
1886
1887
Steve Block44f0eee2011-05-26 01:26:41 +01001888Sampler* Logger::sampler() {
1889 return ticker_;
1890}
1891
1892
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001893FILE* Logger::TearDown() {
1894 if (!is_initialized_) return NULL;
Steve Block44f0eee2011-05-26 01:26:41 +01001895 is_initialized_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001896
1897 // Stop the profiler before closing the file.
1898 if (profiler_ != NULL) {
1899 profiler_->Disengage();
1900 delete profiler_;
1901 profiler_ = NULL;
1902 }
1903
Steve Blocka7e24c12009-10-30 11:49:00 +00001904 delete ticker_;
1905 ticker_ = NULL;
1906
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001907 if (perf_basic_logger_) {
1908 removeCodeEventListener(perf_basic_logger_);
1909 delete perf_basic_logger_;
1910 perf_basic_logger_ = NULL;
1911 }
1912
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001913 if (ll_logger_) {
1914 removeCodeEventListener(ll_logger_);
1915 delete ll_logger_;
1916 ll_logger_ = NULL;
1917 }
1918
1919 if (jit_logger_) {
1920 removeCodeEventListener(jit_logger_);
1921 delete jit_logger_;
1922 jit_logger_ = NULL;
1923 }
1924
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001925 return log_->Close();
Steve Blocka7e24c12009-10-30 11:49:00 +00001926}
1927
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001928} // namespace internal
1929} // namespace v8