blob: 93111a2e7eba008c025ccc141026cf38e7caf2c5 [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"
Ben Murdochda12d292016-06-02 14:46:10 +010016#include "src/interpreter/bytecodes.h"
17#include "src/interpreter/interpreter.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018#include "src/log-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019#include "src/log-utils.h"
20#include "src/macro-assembler.h"
Ben Murdochda12d292016-06-02 14:46:10 +010021#include "src/perf-jit.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022#include "src/profiler/cpu-profiler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023#include "src/runtime-profiler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024#include "src/string-stream.h"
25#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000026
27namespace v8 {
28namespace internal {
29
Steve Blocka7e24c12009-10-30 11:49:00 +000030
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031#define DECLARE_EVENT(ignore1, name) name,
32static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
33 LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)
Steve Blocka7e24c12009-10-30 11:49:00 +000034};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035#undef DECLARE_EVENT
Steve Blocka7e24c12009-10-30 11:49:00 +000036
37
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038#define CALL_LISTENERS(Call) \
39for (int i = 0; i < listeners_.length(); ++i) { \
40 listeners_[i]->Call; \
Steve Blocka7e24c12009-10-30 11:49:00 +000041}
42
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043#define PROFILER_LOG(Call) \
44 do { \
45 CpuProfiler* cpu_profiler = isolate_->cpu_profiler(); \
46 if (cpu_profiler->is_profiling()) { \
47 cpu_profiler->Call; \
48 } \
49 } while (false);
Steve Blocka7e24c12009-10-30 11:49:00 +000050
Ben Murdochda12d292016-06-02 14:46:10 +010051static const char* ComputeMarker(SharedFunctionInfo* shared,
52 AbstractCode* code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053 switch (code->kind()) {
Ben Murdochda12d292016-06-02 14:46:10 +010054 case AbstractCode::FUNCTION:
55 case AbstractCode::INTERPRETED_FUNCTION:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 return shared->optimization_disabled() ? "" : "~";
Ben Murdochda12d292016-06-02 14:46:10 +010057 case AbstractCode::OPTIMIZED_FUNCTION:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 return "*";
59 default:
60 return "";
Steve Blocka7e24c12009-10-30 11:49:00 +000061 }
62}
63
64
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065class CodeEventLogger::NameBuffer {
Ben Murdoch257744e2011-11-30 15:57:28 +000066 public:
67 NameBuffer() { Reset(); }
68
69 void Reset() {
70 utf8_pos_ = 0;
71 }
72
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073 void Init(Logger::LogEventsAndTags tag) {
74 Reset();
75 AppendBytes(kLogEventsNames[tag]);
76 AppendByte(':');
77 }
78
79 void AppendName(Name* name) {
80 if (name->IsString()) {
81 AppendString(String::cast(name));
82 } else {
83 Symbol* symbol = Symbol::cast(name);
84 AppendBytes("symbol(");
85 if (!symbol->name()->IsUndefined()) {
86 AppendBytes("\"");
87 AppendString(String::cast(symbol->name()));
88 AppendBytes("\" ");
89 }
90 AppendBytes("hash ");
91 AppendHex(symbol->Hash());
92 AppendByte(')');
93 }
94 }
95
Ben Murdoch257744e2011-11-30 15:57:28 +000096 void AppendString(String* str) {
97 if (str == NULL) return;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010098 int uc16_length = Min(str->length(), kUtf16BufferSize);
99 String::WriteToFlat(str, utf16_buffer, 0, uc16_length);
100 int previous = unibrow::Utf16::kNoPreviousCharacter;
Ben Murdoch257744e2011-11-30 15:57:28 +0000101 for (int i = 0; i < uc16_length && utf8_pos_ < kUtf8BufferSize; ++i) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100102 uc16 c = utf16_buffer[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103 if (c <= unibrow::Utf8::kMaxOneByteChar) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000104 utf8_buffer_[utf8_pos_++] = static_cast<char>(c);
105 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100106 int char_length = unibrow::Utf8::Length(c, previous);
Ben Murdoch257744e2011-11-30 15:57:28 +0000107 if (utf8_pos_ + char_length > kUtf8BufferSize) break;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100108 unibrow::Utf8::Encode(utf8_buffer_ + utf8_pos_, c, previous);
Ben Murdoch257744e2011-11-30 15:57:28 +0000109 utf8_pos_ += char_length;
110 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100111 previous = c;
Ben Murdoch257744e2011-11-30 15:57:28 +0000112 }
113 }
114
115 void AppendBytes(const char* bytes, int size) {
116 size = Min(size, kUtf8BufferSize - utf8_pos_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117 MemCopy(utf8_buffer_ + utf8_pos_, bytes, size);
Ben Murdoch257744e2011-11-30 15:57:28 +0000118 utf8_pos_ += size;
119 }
120
121 void AppendBytes(const char* bytes) {
122 AppendBytes(bytes, StrLength(bytes));
123 }
124
125 void AppendByte(char c) {
126 if (utf8_pos_ >= kUtf8BufferSize) return;
127 utf8_buffer_[utf8_pos_++] = c;
128 }
129
130 void AppendInt(int n) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 int space = kUtf8BufferSize - utf8_pos_;
132 if (space <= 0) return;
133 Vector<char> buffer(utf8_buffer_ + utf8_pos_, space);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000134 int size = SNPrintF(buffer, "%d", n);
135 if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
136 utf8_pos_ += size;
137 }
138 }
139
140 void AppendHex(uint32_t n) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141 int space = kUtf8BufferSize - utf8_pos_;
142 if (space <= 0) return;
143 Vector<char> buffer(utf8_buffer_ + utf8_pos_, space);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144 int size = SNPrintF(buffer, "%x", n);
Ben Murdoch257744e2011-11-30 15:57:28 +0000145 if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
146 utf8_pos_ += size;
147 }
148 }
149
150 const char* get() { return utf8_buffer_; }
151 int size() const { return utf8_pos_; }
152
153 private:
154 static const int kUtf8BufferSize = 512;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 static const int kUtf16BufferSize = kUtf8BufferSize;
Ben Murdoch257744e2011-11-30 15:57:28 +0000156
157 int utf8_pos_;
158 char utf8_buffer_[kUtf8BufferSize];
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100159 uc16 utf16_buffer[kUtf16BufferSize];
Ben Murdoch257744e2011-11-30 15:57:28 +0000160};
161
162
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000163CodeEventLogger::CodeEventLogger() : name_buffer_(new NameBuffer) { }
164
165CodeEventLogger::~CodeEventLogger() { delete name_buffer_; }
166
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100168 AbstractCode* code, const char* comment) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 name_buffer_->Init(tag);
170 name_buffer_->AppendBytes(comment);
171 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
172}
173
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100175 AbstractCode* code, Name* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 name_buffer_->Init(tag);
177 name_buffer_->AppendName(name);
178 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
179}
180
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100182 AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 SharedFunctionInfo* shared,
Ben Murdochda12d292016-06-02 14:46:10 +0100184 CompilationInfo* info, Name* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 name_buffer_->Init(tag);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 name_buffer_->AppendBytes(ComputeMarker(shared, code));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000187 name_buffer_->AppendName(name);
188 LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
189}
190
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100192 AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193 SharedFunctionInfo* shared,
Ben Murdochda12d292016-06-02 14:46:10 +0100194 CompilationInfo* info, Name* source,
195 int line, int column) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 name_buffer_->Init(tag);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197 name_buffer_->AppendBytes(ComputeMarker(shared, code));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198 name_buffer_->AppendString(shared->DebugName());
199 name_buffer_->AppendByte(' ');
200 if (source->IsString()) {
201 name_buffer_->AppendString(String::cast(source));
202 } else {
203 name_buffer_->AppendBytes("symbol(hash ");
204 name_buffer_->AppendHex(Name::cast(source)->Hash());
205 name_buffer_->AppendByte(')');
206 }
207 name_buffer_->AppendByte(':');
208 name_buffer_->AppendInt(line);
209 LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
210}
211
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100213 AbstractCode* code, int args_count) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 name_buffer_->Init(tag);
215 name_buffer_->AppendInt(args_count);
216 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
217}
218
Ben Murdochda12d292016-06-02 14:46:10 +0100219void CodeEventLogger::RegExpCodeCreateEvent(AbstractCode* code,
220 String* source) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 name_buffer_->Init(Logger::REG_EXP_TAG);
222 name_buffer_->AppendString(source);
223 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
224}
225
226
227// Linux perf tool logging support
228class PerfBasicLogger : public CodeEventLogger {
229 public:
230 PerfBasicLogger();
Ben Murdochda12d292016-06-02 14:46:10 +0100231 ~PerfBasicLogger() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232
Ben Murdochda12d292016-06-02 14:46:10 +0100233 void CodeMoveEvent(AbstractCode* from, Address to) override {}
234 void CodeDisableOptEvent(AbstractCode* code,
235 SharedFunctionInfo* shared) override {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236
237 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100238 void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo* shared,
239 const char* name, int length) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240
241 // Extension added to V8 log file name to get the low-level log name.
242 static const char kFilenameFormatString[];
243 static const int kFilenameBufferPadding;
244
245 // File buffer size of the low-level log. We don't use the default to
246 // minimize the associated overhead.
247 static const int kLogBufferSize = 2 * MB;
248
249 FILE* perf_output_handle_;
250};
251
252const char PerfBasicLogger::kFilenameFormatString[] = "/tmp/perf-%d.map";
253// Extra space for the PID in the filename
254const int PerfBasicLogger::kFilenameBufferPadding = 16;
255
256PerfBasicLogger::PerfBasicLogger()
257 : perf_output_handle_(NULL) {
258 // Open the perf JIT dump file.
259 int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
260 ScopedVector<char> perf_dump_name(bufferSize);
261 int size = SNPrintF(
262 perf_dump_name,
263 kFilenameFormatString,
264 base::OS::GetCurrentProcessId());
265 CHECK_NE(size, -1);
266 perf_output_handle_ =
267 base::OS::FOpen(perf_dump_name.start(), base::OS::LogFileOpenMode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 CHECK_NOT_NULL(perf_output_handle_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 setvbuf(perf_output_handle_, NULL, _IOFBF, kLogBufferSize);
270}
271
272
273PerfBasicLogger::~PerfBasicLogger() {
274 fclose(perf_output_handle_);
275 perf_output_handle_ = NULL;
276}
277
Ben Murdochda12d292016-06-02 14:46:10 +0100278void PerfBasicLogger::LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
279 const char* name, int length) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 if (FLAG_perf_basic_prof_only_functions &&
Ben Murdochda12d292016-06-02 14:46:10 +0100281 (code->kind() != AbstractCode::FUNCTION &&
282 code->kind() != AbstractCode::INTERPRETED_FUNCTION &&
283 code->kind() != AbstractCode::OPTIMIZED_FUNCTION)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284 return;
285 }
286
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287 base::OS::FPrint(perf_output_handle_, "%llx %x %.*s\n",
288 reinterpret_cast<uint64_t>(code->instruction_start()),
289 code->instruction_size(), length, name);
290}
291
292
293// Low-level logging support.
294#define LL_LOG(Call) if (ll_logger_) ll_logger_->Call;
295
296class LowLevelLogger : public CodeEventLogger {
297 public:
298 explicit LowLevelLogger(const char* file_name);
Ben Murdochda12d292016-06-02 14:46:10 +0100299 ~LowLevelLogger() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000300
Ben Murdochda12d292016-06-02 14:46:10 +0100301 void CodeMoveEvent(AbstractCode* from, Address to) override;
302 void CodeDisableOptEvent(AbstractCode* code,
303 SharedFunctionInfo* shared) override {}
304 void SnapshotPositionEvent(HeapObject* obj, int pos);
305 void CodeMovingGCEvent() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306
307 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100308 void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo* shared,
309 const char* name, int length) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310
311 // Low-level profiling event structures.
312 struct CodeCreateStruct {
313 static const char kTag = 'C';
314
315 int32_t name_size;
316 Address code_address;
317 int32_t code_size;
318 };
319
320
321 struct CodeMoveStruct {
322 static const char kTag = 'M';
323
324 Address from_address;
325 Address to_address;
326 };
327
328
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329 static const char kCodeMovingGCTag = 'G';
330
331
332 // Extension added to V8 log file name to get the low-level log name.
333 static const char kLogExt[];
334
335 // File buffer size of the low-level log. We don't use the default to
336 // minimize the associated overhead.
337 static const int kLogBufferSize = 2 * MB;
338
339 void LogCodeInfo();
340 void LogWriteBytes(const char* bytes, int size);
341
342 template <typename T>
343 void LogWriteStruct(const T& s) {
344 char tag = T::kTag;
345 LogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag));
346 LogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s));
347 }
348
349 FILE* ll_output_handle_;
350};
351
352const char LowLevelLogger::kLogExt[] = ".ll";
353
354LowLevelLogger::LowLevelLogger(const char* name)
355 : ll_output_handle_(NULL) {
356 // Open the low-level log file.
357 size_t len = strlen(name);
358 ScopedVector<char> ll_name(static_cast<int>(len + sizeof(kLogExt)));
359 MemCopy(ll_name.start(), name, len);
360 MemCopy(ll_name.start() + len, kLogExt, sizeof(kLogExt));
361 ll_output_handle_ =
362 base::OS::FOpen(ll_name.start(), base::OS::LogFileOpenMode);
363 setvbuf(ll_output_handle_, NULL, _IOFBF, kLogBufferSize);
364
365 LogCodeInfo();
366}
367
368
369LowLevelLogger::~LowLevelLogger() {
370 fclose(ll_output_handle_);
371 ll_output_handle_ = NULL;
372}
373
374
375void LowLevelLogger::LogCodeInfo() {
376#if V8_TARGET_ARCH_IA32
377 const char arch[] = "ia32";
378#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
379 const char arch[] = "x64";
380#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
381 const char arch[] = "x32";
382#elif V8_TARGET_ARCH_ARM
383 const char arch[] = "arm";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000384#elif V8_TARGET_ARCH_PPC
385 const char arch[] = "ppc";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000386#elif V8_TARGET_ARCH_MIPS
387 const char arch[] = "mips";
388#elif V8_TARGET_ARCH_X87
389 const char arch[] = "x87";
390#elif V8_TARGET_ARCH_ARM64
391 const char arch[] = "arm64";
Ben Murdochda12d292016-06-02 14:46:10 +0100392#elif V8_TARGET_ARCH_S390
393 const char arch[] = "s390";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394#else
395 const char arch[] = "unknown";
396#endif
397 LogWriteBytes(arch, sizeof(arch));
398}
399
Ben Murdochda12d292016-06-02 14:46:10 +0100400void LowLevelLogger::LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
401 const char* name, int length) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000402 CodeCreateStruct event;
403 event.name_size = length;
404 event.code_address = code->instruction_start();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000405 event.code_size = code->instruction_size();
406 LogWriteStruct(event);
407 LogWriteBytes(name, length);
408 LogWriteBytes(
409 reinterpret_cast<const char*>(code->instruction_start()),
410 code->instruction_size());
411}
412
Ben Murdochda12d292016-06-02 14:46:10 +0100413void LowLevelLogger::CodeMoveEvent(AbstractCode* from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000414 CodeMoveStruct event;
Ben Murdochda12d292016-06-02 14:46:10 +0100415 event.from_address = from->instruction_start();
416 size_t header_size = from->instruction_start() - from->address();
417 event.to_address = to + header_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000418 LogWriteStruct(event);
419}
420
421
422void LowLevelLogger::LogWriteBytes(const char* bytes, int size) {
423 size_t rv = fwrite(bytes, 1, size, ll_output_handle_);
424 DCHECK(static_cast<size_t>(size) == rv);
425 USE(rv);
426}
427
428
429void LowLevelLogger::CodeMovingGCEvent() {
430 const char tag = kCodeMovingGCTag;
431
432 LogWriteBytes(&tag, sizeof(tag));
433}
434
435
436#define JIT_LOG(Call) if (jit_logger_) jit_logger_->Call;
437
438
439class JitLogger : public CodeEventLogger {
440 public:
441 explicit JitLogger(JitCodeEventHandler code_event_handler);
442
Ben Murdochda12d292016-06-02 14:46:10 +0100443 void CodeMoveEvent(AbstractCode* from, Address to) override;
444 void CodeDisableOptEvent(AbstractCode* code,
445 SharedFunctionInfo* shared) override {}
446 void AddCodeLinePosInfoEvent(void* jit_handler_data, int pc_offset,
447 int position,
448 JitCodeEvent::PositionType position_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000449
450 void* StartCodePosInfoEvent();
Ben Murdochda12d292016-06-02 14:46:10 +0100451 void EndCodePosInfoEvent(AbstractCode* code, void* jit_handler_data);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000452
453 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100454 void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo* shared,
455 const char* name, int length) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000456
457 JitCodeEventHandler code_event_handler_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000458 base::Mutex logger_mutex_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000459};
460
461
462JitLogger::JitLogger(JitCodeEventHandler code_event_handler)
463 : code_event_handler_(code_event_handler) {
464}
465
Ben Murdochda12d292016-06-02 14:46:10 +0100466void JitLogger::LogRecordedBuffer(AbstractCode* code,
467 SharedFunctionInfo* shared, const char* name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000468 int length) {
469 JitCodeEvent event;
470 memset(&event, 0, sizeof(event));
471 event.type = JitCodeEvent::CODE_ADDED;
472 event.code_start = code->instruction_start();
473 event.code_len = code->instruction_size();
474 Handle<SharedFunctionInfo> shared_function_handle;
475 if (shared && shared->script()->IsScript()) {
476 shared_function_handle = Handle<SharedFunctionInfo>(shared);
477 }
478 event.script = ToApiHandle<v8::UnboundScript>(shared_function_handle);
479 event.name.str = name;
480 event.name.len = length;
481 code_event_handler_(&event);
482}
483
Ben Murdochda12d292016-06-02 14:46:10 +0100484void JitLogger::CodeMoveEvent(AbstractCode* from, Address to) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000485 base::LockGuard<base::Mutex> guard(&logger_mutex_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000486
487 JitCodeEvent event;
488 event.type = JitCodeEvent::CODE_MOVED;
Ben Murdochda12d292016-06-02 14:46:10 +0100489 event.code_start = from->instruction_start();
490 event.code_len = from->instruction_size();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000491
492 // Calculate the header size.
Ben Murdochda12d292016-06-02 14:46:10 +0100493 const size_t header_size = from->instruction_start() - from->address();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494
495 // Calculate the new start address of the instructions.
Ben Murdochda12d292016-06-02 14:46:10 +0100496 event.new_code_start = to + header_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000497
498 code_event_handler_(&event);
499}
500
501void JitLogger::AddCodeLinePosInfoEvent(
502 void* jit_handler_data,
503 int pc_offset,
504 int position,
505 JitCodeEvent::PositionType position_type) {
506 JitCodeEvent event;
507 memset(&event, 0, sizeof(event));
508 event.type = JitCodeEvent::CODE_ADD_LINE_POS_INFO;
509 event.user_data = jit_handler_data;
510 event.line_info.offset = pc_offset;
511 event.line_info.pos = position;
512 event.line_info.position_type = position_type;
513
514 code_event_handler_(&event);
515}
516
517
518void* JitLogger::StartCodePosInfoEvent() {
519 JitCodeEvent event;
520 memset(&event, 0, sizeof(event));
521 event.type = JitCodeEvent::CODE_START_LINE_INFO_RECORDING;
522
523 code_event_handler_(&event);
524 return event.user_data;
525}
526
Ben Murdochda12d292016-06-02 14:46:10 +0100527void JitLogger::EndCodePosInfoEvent(AbstractCode* code,
528 void* jit_handler_data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000529 JitCodeEvent event;
530 memset(&event, 0, sizeof(event));
531 event.type = JitCodeEvent::CODE_END_LINE_INFO_RECORDING;
532 event.code_start = code->instruction_start();
533 event.user_data = jit_handler_data;
534
535 code_event_handler_(&event);
536}
537
538
539// The Profiler samples pc and sp values for the main thread.
540// Each sample is appended to a circular buffer.
541// An independent thread removes data and writes it to the log.
542// This design minimizes the time spent in the sampler.
543//
544class Profiler: public base::Thread {
545 public:
546 explicit Profiler(Isolate* isolate);
547 void Engage();
548 void Disengage();
549
550 // Inserts collected profiling data into buffer.
551 void Insert(TickSample* sample) {
552 if (paused_)
553 return;
554
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400555 if (Succ(head_) == static_cast<int>(base::NoBarrier_Load(&tail_))) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000556 overflow_ = true;
557 } else {
558 buffer_[head_] = *sample;
559 head_ = Succ(head_);
560 buffer_semaphore_.Signal(); // Tell we have an element.
561 }
562 }
563
564 virtual void Run();
565
566 // Pause and Resume TickSample data collection.
567 void pause() { paused_ = true; }
568 void resume() { paused_ = false; }
569
570 private:
571 // Waits for a signal and removes profiling data.
572 bool Remove(TickSample* sample) {
573 buffer_semaphore_.Wait(); // Wait for an element.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400574 *sample = buffer_[base::NoBarrier_Load(&tail_)];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575 bool result = overflow_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400576 base::NoBarrier_Store(&tail_, static_cast<base::Atomic32>(
577 Succ(base::NoBarrier_Load(&tail_))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578 overflow_ = false;
579 return result;
580 }
581
582 // Returns the next index in the cyclic buffer.
583 int Succ(int index) { return (index + 1) % kBufferSize; }
584
585 Isolate* isolate_;
586 // Cyclic buffer for communicating profiling samples
587 // between the signal handler and the worker thread.
588 static const int kBufferSize = 128;
589 TickSample buffer_[kBufferSize]; // Buffer storage.
590 int head_; // Index to the buffer head.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400591 base::Atomic32 tail_; // Index to the buffer tail.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592 bool overflow_; // Tell whether a buffer overflow has occurred.
593 // Sempahore used for buffer synchronization.
594 base::Semaphore buffer_semaphore_;
595
596 // Tells whether profiler is engaged, that is, processing thread is stated.
597 bool engaged_;
598
599 // Tells whether worker thread should continue running.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400600 base::Atomic32 running_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601
602 // Tells whether we are currently recording tick samples.
603 bool paused_;
604};
605
606
607//
608// Ticker used to provide ticks to the profiler and the sliding state
609// window.
610//
611class Ticker: public Sampler {
612 public:
613 Ticker(Isolate* isolate, int interval):
614 Sampler(isolate, interval),
615 profiler_(NULL) {}
616
617 ~Ticker() { if (IsActive()) Stop(); }
618
619 virtual void Tick(TickSample* sample) {
620 if (profiler_) profiler_->Insert(sample);
621 }
622
623 void SetProfiler(Profiler* profiler) {
624 DCHECK(profiler_ == NULL);
625 profiler_ = profiler;
626 IncreaseProfilingDepth();
627 if (!IsActive()) Start();
628 }
629
630 void ClearProfiler() {
631 profiler_ = NULL;
632 if (IsActive()) Stop();
633 DecreaseProfilingDepth();
634 }
635
636 private:
637 Profiler* profiler_;
638};
639
640
641//
642// Profiler implementation.
643//
644Profiler::Profiler(Isolate* isolate)
645 : base::Thread(Options("v8:Profiler")),
646 isolate_(isolate),
647 head_(0),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648 overflow_(false),
649 buffer_semaphore_(0),
650 engaged_(false),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400651 paused_(false) {
652 base::NoBarrier_Store(&tail_, 0);
653 base::NoBarrier_Store(&running_, 0);
654}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000655
656
657void Profiler::Engage() {
658 if (engaged_) return;
659 engaged_ = true;
660
661 std::vector<base::OS::SharedLibraryAddress> addresses =
662 base::OS::GetSharedLibraryAddresses();
663 for (size_t i = 0; i < addresses.size(); ++i) {
664 LOG(isolate_, SharedLibraryEvent(
665 addresses[i].library_path, addresses[i].start, addresses[i].end));
666 }
667
668 // Start thread processing the profiler buffer.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400669 base::NoBarrier_Store(&running_, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000670 Start();
671
672 // Register to get ticks.
673 Logger* logger = isolate_->logger();
674 logger->ticker_->SetProfiler(this);
675
676 logger->ProfilerBeginEvent();
677}
678
679
680void Profiler::Disengage() {
681 if (!engaged_) return;
682
683 // Stop receiving ticks.
684 isolate_->logger()->ticker_->ClearProfiler();
685
686 // Terminate the worker thread by setting running_ to false,
687 // inserting a fake element in the queue and then wait for
688 // the thread to terminate.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400689 base::NoBarrier_Store(&running_, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000690 TickSample sample;
691 // Reset 'paused_' flag, otherwise semaphore may not be signalled.
692 resume();
693 Insert(&sample);
694 Join();
695
696 LOG(isolate_, UncheckedStringEvent("profiler", "end"));
697}
698
699
700void Profiler::Run() {
701 TickSample sample;
702 bool overflow = Remove(&sample);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400703 while (base::NoBarrier_Load(&running_)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000704 LOG(isolate_, TickEvent(&sample, overflow));
705 overflow = Remove(&sample);
706 }
707}
708
709
710//
711// Logger class implementation.
712//
713
714Logger::Logger(Isolate* isolate)
Ben Murdochda12d292016-06-02 14:46:10 +0100715 : isolate_(isolate),
716 ticker_(NULL),
717 profiler_(NULL),
718 log_events_(NULL),
719 is_logging_(false),
720 log_(new Log(this)),
721 perf_basic_logger_(NULL),
722 perf_jit_logger_(NULL),
723 ll_logger_(NULL),
724 jit_logger_(NULL),
725 listeners_(5),
726 is_initialized_(false) {}
Ben Murdoch257744e2011-11-30 15:57:28 +0000727
Steve Block44f0eee2011-05-26 01:26:41 +0100728Logger::~Logger() {
729 delete log_;
730}
Steve Blocka7e24c12009-10-30 11:49:00 +0000731
Ben Murdoch257744e2011-11-30 15:57:28 +0000732
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000733void Logger::addCodeEventListener(CodeEventListener* listener) {
734 DCHECK(!hasCodeEventListener(listener));
735 listeners_.Add(listener);
736}
737
738
739void Logger::removeCodeEventListener(CodeEventListener* listener) {
740 DCHECK(hasCodeEventListener(listener));
741 listeners_.RemoveElement(listener);
742}
743
744
745bool Logger::hasCodeEventListener(CodeEventListener* listener) {
746 return listeners_.Contains(listener);
747}
Steve Blocka7e24c12009-10-30 11:49:00 +0000748
749
750void Logger::ProfilerBeginEvent() {
Steve Block44f0eee2011-05-26 01:26:41 +0100751 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000752 Log::MessageBuilder msg(log_);
753 msg.Append("profiler,\"begin\",%d", kSamplingIntervalMs);
Steve Blocka7e24c12009-10-30 11:49:00 +0000754 msg.WriteToLogFile();
755}
756
Steve Blocka7e24c12009-10-30 11:49:00 +0000757
Steve Blocka7e24c12009-10-30 11:49:00 +0000758void Logger::StringEvent(const char* name, const char* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000759 if (FLAG_log) UncheckedStringEvent(name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000760}
761
762
Steve Blocka7e24c12009-10-30 11:49:00 +0000763void Logger::UncheckedStringEvent(const char* name, const char* value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100764 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000765 Log::MessageBuilder msg(log_);
766 msg.Append("%s,\"%s\"", name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000767 msg.WriteToLogFile();
768}
Steve Blocka7e24c12009-10-30 11:49:00 +0000769
770
771void Logger::IntEvent(const char* name, int value) {
Steve Block6ded16b2010-05-10 14:33:55 +0100772 if (FLAG_log) UncheckedIntEvent(name, value);
Steve Block6ded16b2010-05-10 14:33:55 +0100773}
774
775
Ben Murdochf87a2032010-10-22 12:50:53 +0100776void Logger::IntPtrTEvent(const char* name, intptr_t value) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100777 if (FLAG_log) UncheckedIntPtrTEvent(name, value);
Ben Murdochf87a2032010-10-22 12:50:53 +0100778}
779
780
Steve Block6ded16b2010-05-10 14:33:55 +0100781void Logger::UncheckedIntEvent(const char* name, int value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100782 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000783 Log::MessageBuilder msg(log_);
784 msg.Append("%s,%d", name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000785 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000786}
787
788
Ben Murdochf87a2032010-10-22 12:50:53 +0100789void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100790 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000791 Log::MessageBuilder msg(log_);
792 msg.Append("%s,%" V8_PTR_PREFIX "d", name, value);
Ben Murdochf87a2032010-10-22 12:50:53 +0100793 msg.WriteToLogFile();
794}
Ben Murdochf87a2032010-10-22 12:50:53 +0100795
796
Steve Blocka7e24c12009-10-30 11:49:00 +0000797void Logger::HandleEvent(const char* name, Object** location) {
Steve Block44f0eee2011-05-26 01:26:41 +0100798 if (!log_->IsEnabled() || !FLAG_log_handles) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000799 Log::MessageBuilder msg(log_);
800 msg.Append("%s,0x%" V8PRIxPTR, name, location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000801 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000802}
803
804
Steve Blocka7e24c12009-10-30 11:49:00 +0000805// ApiEvent is private so all the calls come from the Logger class. It is the
806// caller's responsibility to ensure that log is enabled and that
807// FLAG_log_api is true.
808void Logger::ApiEvent(const char* format, ...) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000809 DCHECK(log_->IsEnabled() && FLAG_log_api);
810 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000811 va_list ap;
812 va_start(ap, format);
813 msg.AppendVA(format, ap);
814 va_end(ap);
815 msg.WriteToLogFile();
816}
Steve Blocka7e24c12009-10-30 11:49:00 +0000817
818
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000819void Logger::ApiSecurityCheck() {
Steve Block44f0eee2011-05-26 01:26:41 +0100820 if (!log_->IsEnabled() || !FLAG_log_api) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000821 ApiEvent("api,check-security");
Steve Blocka7e24c12009-10-30 11:49:00 +0000822}
823
824
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000825void Logger::SharedLibraryEvent(const std::string& library_path,
Steve Blocka7e24c12009-10-30 11:49:00 +0000826 uintptr_t start,
827 uintptr_t end) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000828 if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000829 Log::MessageBuilder msg(log_);
830 msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR,
831 library_path.c_str(), start, end);
Steve Blocka7e24c12009-10-30 11:49:00 +0000832 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000833}
834
835
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000836void Logger::CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) {
837 PROFILER_LOG(CodeDeoptEvent(code, pc, fp_to_sp_delta));
838 if (!log_->IsEnabled() || !FLAG_log_internal_timer_events) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000839 Log::MessageBuilder msg(log_);
840 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
841 msg.Append("code-deopt,%ld,%d", since_epoch, code->CodeSize());
Steve Blocka7e24c12009-10-30 11:49:00 +0000842 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000843}
844
845
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846void Logger::CurrentTimeEvent() {
847 if (!log_->IsEnabled()) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000848 DCHECK(FLAG_log_timer_events || FLAG_prof_cpp);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000849 Log::MessageBuilder msg(log_);
850 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
851 msg.Append("current-time,%ld", since_epoch);
852 msg.WriteToLogFile();
853}
854
855
856void Logger::TimerEvent(Logger::StartEnd se, const char* name) {
857 if (!log_->IsEnabled()) return;
858 DCHECK(FLAG_log_internal_timer_events);
859 Log::MessageBuilder msg(log_);
860 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
861 const char* format = (se == START) ? "timer-event-start,\"%s\",%ld"
862 : "timer-event-end,\"%s\",%ld";
863 msg.Append(format, name, since_epoch);
864 msg.WriteToLogFile();
865}
866
867
868void Logger::EnterExternal(Isolate* isolate) {
869 LOG(isolate, TimerEvent(START, TimerEventExternal::name()));
870 DCHECK(isolate->current_vm_state() == JS);
871 isolate->set_current_vm_state(EXTERNAL);
872}
873
874
875void Logger::LeaveExternal(Isolate* isolate) {
876 LOG(isolate, TimerEvent(END, TimerEventExternal::name()));
877 DCHECK(isolate->current_vm_state() == EXTERNAL);
878 isolate->set_current_vm_state(JS);
879}
880
881
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882template <class TimerEvent>
883void TimerEventScope<TimerEvent>::LogTimerEvent(Logger::StartEnd se) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400884 Logger::CallEventLogger(isolate_, TimerEvent::name(), se,
885 TimerEvent::expose_to_api());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000886}
887
888
889// Instantiate template methods.
890#define V(TimerName, expose) \
891 template void TimerEventScope<TimerEvent##TimerName>::LogTimerEvent( \
892 Logger::StartEnd se);
893TIMER_EVENTS_LIST(V)
894#undef V
895
896
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000897namespace {
898// Emits the source code of a regexp. Used by regexp events.
899void LogRegExpSource(Handle<JSRegExp> regexp, Isolate* isolate,
900 Log::MessageBuilder* msg) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000901 // Prints "/" + re.source + "/" +
902 // (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
Steve Blocka7e24c12009-10-30 11:49:00 +0000903
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000904 Handle<Object> source =
Ben Murdochda12d292016-06-02 14:46:10 +0100905 JSReceiver::GetProperty(isolate, regexp, "source").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000906 if (!source->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000907 msg->Append("no source");
Steve Blocka7e24c12009-10-30 11:49:00 +0000908 return;
909 }
910
911 switch (regexp->TypeTag()) {
912 case JSRegExp::ATOM:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000913 msg->Append('a');
Steve Blocka7e24c12009-10-30 11:49:00 +0000914 break;
915 default:
916 break;
917 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000918 msg->Append('/');
919 msg->AppendDetailed(*Handle<String>::cast(source), false);
920 msg->Append('/');
Steve Blocka7e24c12009-10-30 11:49:00 +0000921
922 // global flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000923 Handle<Object> global =
Ben Murdochda12d292016-06-02 14:46:10 +0100924 JSReceiver::GetProperty(isolate, regexp, "global").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000925 if (global->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000926 msg->Append('g');
Steve Blocka7e24c12009-10-30 11:49:00 +0000927 }
928 // ignorecase flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929 Handle<Object> ignorecase =
Ben Murdochda12d292016-06-02 14:46:10 +0100930 JSReceiver::GetProperty(isolate, regexp, "ignoreCase").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000931 if (ignorecase->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932 msg->Append('i');
Steve Blocka7e24c12009-10-30 11:49:00 +0000933 }
934 // multiline flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000935 Handle<Object> multiline =
Ben Murdochda12d292016-06-02 14:46:10 +0100936 JSReceiver::GetProperty(isolate, regexp, "multiline").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000937 if (multiline->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000938 msg->Append('m');
Steve Blocka7e24c12009-10-30 11:49:00 +0000939 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000940}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000941} // namespace
Steve Blocka7e24c12009-10-30 11:49:00 +0000942
943
944void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
Steve Block44f0eee2011-05-26 01:26:41 +0100945 if (!log_->IsEnabled() || !FLAG_log_regexp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000946 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000947 msg.Append("regexp-compile,");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948 LogRegExpSource(regexp, isolate_, &msg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000949 msg.Append(in_cache ? ",hit" : ",miss");
Steve Blocka7e24c12009-10-30 11:49:00 +0000950 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000951}
952
953
Steve Blocka7e24c12009-10-30 11:49:00 +0000954void Logger::ApiNamedPropertyAccess(const char* tag,
955 JSObject* holder,
956 Object* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000957 DCHECK(name->IsName());
Steve Block44f0eee2011-05-26 01:26:41 +0100958 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000959 String* class_name_obj = holder->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +0000961 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000963 base::SmartArrayPointer<char> property_name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000964 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
965 ApiEvent("api,%s,\"%s\",\"%s\"", tag, class_name.get(),
966 property_name.get());
967 } else {
968 Symbol* symbol = Symbol::cast(name);
969 uint32_t hash = symbol->Hash();
970 if (symbol->name()->IsUndefined()) {
971 ApiEvent("api,%s,\"%s\",symbol(hash %x)", tag, class_name.get(), hash);
972 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000973 base::SmartArrayPointer<char> str =
974 String::cast(symbol->name())
975 ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000976 ApiEvent("api,%s,\"%s\",symbol(\"%s\" hash %x)", tag, class_name.get(),
977 str.get(), hash);
978 }
979 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000980}
981
982void Logger::ApiIndexedPropertyAccess(const char* tag,
983 JSObject* holder,
984 uint32_t index) {
Steve Block44f0eee2011-05-26 01:26:41 +0100985 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000986 String* class_name_obj = holder->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000987 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +0000988 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000989 ApiEvent("api,%s,\"%s\",%u", tag, class_name.get(), index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000990}
991
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000992
Steve Blocka7e24c12009-10-30 11:49:00 +0000993void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
Steve Block44f0eee2011-05-26 01:26:41 +0100994 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000995 String* class_name_obj = object->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000996 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +0000997 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 ApiEvent("api,%s,\"%s\"", tag, class_name.get());
Steve Blocka7e24c12009-10-30 11:49:00 +0000999}
1000
1001
1002void Logger::ApiEntryCall(const char* name) {
Steve Block44f0eee2011-05-26 01:26:41 +01001003 if (!log_->IsEnabled() || !FLAG_log_api) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004 ApiEvent("api,%s", name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001005}
1006
1007
1008void Logger::NewEvent(const char* name, void* object, size_t size) {
Steve Block44f0eee2011-05-26 01:26:41 +01001009 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001010 Log::MessageBuilder msg(log_);
1011 msg.Append("new,%s,0x%" V8PRIxPTR ",%u", name, object,
Steve Blocka7e24c12009-10-30 11:49:00 +00001012 static_cast<unsigned int>(size));
1013 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001014}
1015
1016
1017void Logger::DeleteEvent(const char* name, void* object) {
Steve Block44f0eee2011-05-26 01:26:41 +01001018 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001019 Log::MessageBuilder msg(log_);
1020 msg.Append("delete,%s,0x%" V8PRIxPTR, name, object);
Steve Blocka7e24c12009-10-30 11:49:00 +00001021 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001022}
1023
1024
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001025void Logger::CallbackEventInternal(const char* prefix, Name* name,
Steve Blockd0582a62009-12-15 09:54:21 +00001026 Address entry_point) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001027 if (!FLAG_log_code || !log_->IsEnabled()) return;
1028 Log::MessageBuilder msg(log_);
1029 msg.Append("%s,%s,-2,",
Ben Murdochb0fe1622011-05-05 13:52:32 +01001030 kLogEventsNames[CODE_CREATION_EVENT],
1031 kLogEventsNames[CALLBACK_TAG]);
Steve Blockd0582a62009-12-15 09:54:21 +00001032 msg.AppendAddress(entry_point);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001033 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034 base::SmartArrayPointer<char> str =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001035 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1036 msg.Append(",1,\"%s%s\"", prefix, str.get());
1037 } else {
1038 Symbol* symbol = Symbol::cast(name);
1039 if (symbol->name()->IsUndefined()) {
1040 msg.Append(",1,symbol(hash %x)", prefix, symbol->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 msg.Append(",1,symbol(\"%s\" hash %x)", prefix, str.get(),
1046 symbol->Hash());
1047 }
1048 }
Steve Blockd0582a62009-12-15 09:54:21 +00001049 msg.WriteToLogFile();
1050}
Steve Blockd0582a62009-12-15 09:54:21 +00001051
1052
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001053void Logger::CallbackEvent(Name* name, Address entry_point) {
1054 PROFILER_LOG(CallbackEvent(name, entry_point));
1055 CallbackEventInternal("", name, entry_point);
Steve Blockd0582a62009-12-15 09:54:21 +00001056}
1057
1058
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001059void Logger::GetterCallbackEvent(Name* name, Address entry_point) {
1060 PROFILER_LOG(GetterCallbackEvent(name, entry_point));
1061 CallbackEventInternal("get ", name, entry_point);
Steve Blockd0582a62009-12-15 09:54:21 +00001062}
1063
1064
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001065void Logger::SetterCallbackEvent(Name* name, Address entry_point) {
1066 PROFILER_LOG(SetterCallbackEvent(name, entry_point));
1067 CallbackEventInternal("set ", name, entry_point);
1068}
1069
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001070static void AppendCodeCreateHeader(Log::MessageBuilder* msg,
1071 Logger::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +01001072 AbstractCode* code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001073 DCHECK(msg);
1074 msg->Append("%s,%s,%d,",
1075 kLogEventsNames[Logger::CODE_CREATION_EVENT],
1076 kLogEventsNames[tag],
1077 code->kind());
1078 msg->AppendAddress(code->address());
1079 msg->Append(",%d,", code->ExecutableSize());
Steve Blockd0582a62009-12-15 09:54:21 +00001080}
1081
Ben Murdochda12d292016-06-02 14:46:10 +01001082void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
Steve Blocka7e24c12009-10-30 11:49:00 +00001083 const char* comment) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001084 PROFILER_LOG(CodeCreateEvent(tag, code, comment));
1085
1086 if (!is_logging_code_events()) return;
1087 CALL_LISTENERS(CodeCreateEvent(tag, code, comment));
1088
1089 if (!FLAG_log_code || !log_->IsEnabled()) return;
1090 Log::MessageBuilder msg(log_);
1091 AppendCodeCreateHeader(&msg, tag, code);
1092 msg.AppendDoubleQuotedString(comment);
Steve Blocka7e24c12009-10-30 11:49:00 +00001093 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001094}
1095
Ben Murdochda12d292016-06-02 14:46:10 +01001096void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001097 Name* name) {
1098 PROFILER_LOG(CodeCreateEvent(tag, code, name));
1099
1100 if (!is_logging_code_events()) return;
1101 CALL_LISTENERS(CodeCreateEvent(tag, code, name));
1102
1103 if (!FLAG_log_code || !log_->IsEnabled()) return;
1104 Log::MessageBuilder msg(log_);
1105 AppendCodeCreateHeader(&msg, tag, code);
1106 if (name->IsString()) {
1107 msg.Append('"');
1108 msg.AppendDetailed(String::cast(name), false);
1109 msg.Append('"');
1110 } else {
1111 msg.AppendSymbolName(Symbol::cast(name));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001112 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001113 msg.WriteToLogFile();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001114}
1115
Ben Murdochda12d292016-06-02 14:46:10 +01001116void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
1117 SharedFunctionInfo* shared, CompilationInfo* info,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118 Name* name) {
1119 PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, name));
Steve Block44f0eee2011-05-26 01:26:41 +01001120
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001121 if (!is_logging_code_events()) return;
1122 CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, name));
1123
1124 if (!FLAG_log_code || !log_->IsEnabled()) return;
Ben Murdochda12d292016-06-02 14:46:10 +01001125 if (code == AbstractCode::cast(
1126 isolate_->builtins()->builtin(Builtins::kCompileLazy))) {
1127 return;
1128 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001129
1130 Log::MessageBuilder msg(log_);
1131 AppendCodeCreateHeader(&msg, tag, code);
1132 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001133 base::SmartArrayPointer<char> str =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001134 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1135 msg.Append("\"%s\"", str.get());
1136 } else {
1137 msg.AppendSymbolName(Symbol::cast(name));
1138 }
1139 msg.Append(',');
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001140 msg.AppendAddress(shared->address());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001141 msg.Append(",%s", ComputeMarker(shared, code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001142 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001143}
1144
1145
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001146// Although, it is possible to extract source and line from
1147// the SharedFunctionInfo object, we left it to caller
1148// to leave logging functions free from heap allocations.
Ben Murdochda12d292016-06-02 14:46:10 +01001149void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
1150 SharedFunctionInfo* shared, CompilationInfo* info,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001151 Name* source, int line, int column) {
1152 PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, source, line, column));
1153
1154 if (!is_logging_code_events()) return;
1155 CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, source, line,
1156 column));
1157
1158 if (!FLAG_log_code || !log_->IsEnabled()) return;
1159 Log::MessageBuilder msg(log_);
1160 AppendCodeCreateHeader(&msg, tag, code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001161 base::SmartArrayPointer<char> name =
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001162 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001163 msg.Append("\"%s ", name.get());
1164 if (source->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001165 base::SmartArrayPointer<char> sourcestr = String::cast(source)->ToCString(
1166 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001167 msg.Append("%s", sourcestr.get());
1168 } else {
1169 msg.AppendSymbolName(Symbol::cast(source));
1170 }
1171 msg.Append(":%d:%d\",", line, column);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001172 msg.AppendAddress(shared->address());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001173 msg.Append(",%s", ComputeMarker(shared, code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001174 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001175}
1176
Ben Murdochda12d292016-06-02 14:46:10 +01001177void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001178 int args_count) {
1179 PROFILER_LOG(CodeCreateEvent(tag, code, args_count));
1180
1181 if (!is_logging_code_events()) return;
1182 CALL_LISTENERS(CodeCreateEvent(tag, code, args_count));
1183
1184 if (!FLAG_log_code || !log_->IsEnabled()) return;
1185 Log::MessageBuilder msg(log_);
1186 AppendCodeCreateHeader(&msg, tag, code);
1187 msg.Append("\"args_count: %d\"", args_count);
1188 msg.WriteToLogFile();
1189}
1190
Ben Murdochda12d292016-06-02 14:46:10 +01001191void Logger::CodeDisableOptEvent(AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 SharedFunctionInfo* shared) {
1193 PROFILER_LOG(CodeDisableOptEvent(code, shared));
1194
1195 if (!is_logging_code_events()) return;
1196 CALL_LISTENERS(CodeDisableOptEvent(code, shared));
1197
1198 if (!FLAG_log_code || !log_->IsEnabled()) return;
1199 Log::MessageBuilder msg(log_);
1200 msg.Append("%s,", kLogEventsNames[CODE_DISABLE_OPT_EVENT]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001201 base::SmartArrayPointer<char> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001202 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1203 msg.Append("\"%s\",", name.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001204 msg.Append("\"%s\"", GetBailoutReason(shared->disable_optimization_reason()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001205 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001206}
1207
1208
Ben Murdochf87a2032010-10-22 12:50:53 +01001209void Logger::CodeMovingGCEvent() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210 PROFILER_LOG(CodeMovingGCEvent());
1211
1212 if (!is_logging_code_events()) return;
Ben Murdoch257744e2011-11-30 15:57:28 +00001213 if (!log_->IsEnabled() || !FLAG_ll_prof) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214 CALL_LISTENERS(CodeMovingGCEvent());
1215 base::OS::SignalCodeMovingGC();
Ben Murdochf87a2032010-10-22 12:50:53 +01001216}
1217
Ben Murdochda12d292016-06-02 14:46:10 +01001218void Logger::RegExpCodeCreateEvent(AbstractCode* code, String* source) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001219 PROFILER_LOG(RegExpCodeCreateEvent(code, source));
1220
1221 if (!is_logging_code_events()) return;
1222 CALL_LISTENERS(RegExpCodeCreateEvent(code, source));
1223
1224 if (!FLAG_log_code || !log_->IsEnabled()) return;
1225 Log::MessageBuilder msg(log_);
1226 AppendCodeCreateHeader(&msg, REG_EXP_TAG, code);
1227 msg.Append('"');
Steve Blocka7e24c12009-10-30 11:49:00 +00001228 msg.AppendDetailed(source, false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001229 msg.Append('"');
Steve Blocka7e24c12009-10-30 11:49:00 +00001230 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001231}
1232
Ben Murdochda12d292016-06-02 14:46:10 +01001233void Logger::CodeMoveEvent(AbstractCode* from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001234 PROFILER_LOG(CodeMoveEvent(from, to));
1235
1236 if (!is_logging_code_events()) return;
1237 CALL_LISTENERS(CodeMoveEvent(from, to));
Ben Murdochda12d292016-06-02 14:46:10 +01001238 MoveEventInternal(CODE_MOVE_EVENT, from->address(), to);
Steve Blocka7e24c12009-10-30 11:49:00 +00001239}
1240
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001241void Logger::CodeLinePosInfoAddPositionEvent(void* jit_handler_data,
Ben Murdochda12d292016-06-02 14:46:10 +01001242 int pc_offset, int position) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001243 JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1244 pc_offset,
1245 position,
1246 JitCodeEvent::POSITION));
1247}
1248
1249
1250void Logger::CodeLinePosInfoAddStatementPositionEvent(void* jit_handler_data,
1251 int pc_offset,
1252 int position) {
1253 JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1254 pc_offset,
1255 position,
1256 JitCodeEvent::STATEMENT_POSITION));
1257}
1258
1259
1260void Logger::CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder) {
1261 if (jit_logger_ != NULL) {
1262 pos_recorder->AttachJITHandlerData(jit_logger_->StartCodePosInfoEvent());
Ben Murdoch257744e2011-11-30 15:57:28 +00001263 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264}
1265
Ben Murdochda12d292016-06-02 14:46:10 +01001266void Logger::CodeEndLinePosInfoRecordEvent(AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001267 void* jit_handler_data) {
1268 JIT_LOG(EndCodePosInfoEvent(code, jit_handler_data));
1269}
1270
1271
1272void Logger::CodeNameEvent(Address addr, int pos, const char* code_name) {
1273 if (code_name == NULL) return; // Not a code object.
1274 Log::MessageBuilder msg(log_);
1275 msg.Append("%s,%d,", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
1276 msg.AppendDoubleQuotedString(code_name);
1277 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001278}
1279
1280
Steve Block44f0eee2011-05-26 01:26:41 +01001281void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001282 if (!is_logging_code_events()) return;
Steve Block44f0eee2011-05-26 01:26:41 +01001283 MoveEventInternal(SHARED_FUNC_MOVE_EVENT, from, to);
Leon Clarked91b9f72010-01-27 17:25:45 +00001284}
1285
1286
Leon Clarked91b9f72010-01-27 17:25:45 +00001287void Logger::MoveEventInternal(LogEventsAndTags event,
1288 Address from,
1289 Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001290 if (!FLAG_log_code || !log_->IsEnabled()) return;
1291 Log::MessageBuilder msg(log_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001292 msg.Append("%s,", kLogEventsNames[event]);
Leon Clarked91b9f72010-01-27 17:25:45 +00001293 msg.AppendAddress(from);
1294 msg.Append(',');
Ben Murdochb0fe1622011-05-05 13:52:32 +01001295 msg.AppendAddress(to);
Leon Clarked91b9f72010-01-27 17:25:45 +00001296 msg.WriteToLogFile();
1297}
Leon Clarked91b9f72010-01-27 17:25:45 +00001298
1299
Steve Blocka7e24c12009-10-30 11:49:00 +00001300void Logger::ResourceEvent(const char* name, const char* tag) {
Steve Block44f0eee2011-05-26 01:26:41 +01001301 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001302 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001303 msg.Append("%s,%s,", name, tag);
1304
1305 uint32_t sec, usec;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001306 if (base::OS::GetUserTime(&sec, &usec) != -1) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001307 msg.Append("%d,%d,", sec, usec);
1308 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001309 msg.Append("%.0f", base::OS::TimeCurrentMillis());
Steve Blocka7e24c12009-10-30 11:49:00 +00001310 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001311}
1312
1313
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001314void Logger::SuspectReadEvent(Name* name, Object* obj) {
Steve Block44f0eee2011-05-26 01:26:41 +01001315 if (!log_->IsEnabled() || !FLAG_log_suspect) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001316 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001317 String* class_name = obj->IsJSObject()
1318 ? JSObject::cast(obj)->class_name()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001319 : isolate_->heap()->empty_string();
Steve Blocka7e24c12009-10-30 11:49:00 +00001320 msg.Append("suspect-read,");
1321 msg.Append(class_name);
1322 msg.Append(',');
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001323 if (name->IsString()) {
1324 msg.Append('"');
1325 msg.Append(String::cast(name));
1326 msg.Append('"');
1327 } else {
1328 msg.AppendSymbolName(Symbol::cast(name));
1329 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001330 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001331}
1332
1333
1334void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
Steve Block44f0eee2011-05-26 01:26:41 +01001335 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001336 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001337 // Using non-relative system time in order to be able to synchronize with
1338 // external memory profiling events (e.g. DOM memory size).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001339 msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f", space, kind,
1340 base::OS::TimeCurrentMillis());
Steve Blocka7e24c12009-10-30 11:49:00 +00001341 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001342}
1343
1344
1345void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
Steve Block44f0eee2011-05-26 01:26:41 +01001346 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001347 Log::MessageBuilder msg(log_);
1348 msg.Append("heap-sample-end,\"%s\",\"%s\"", space, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001349 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001350}
1351
1352
1353void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
Steve Block44f0eee2011-05-26 01:26:41 +01001354 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001355 Log::MessageBuilder msg(log_);
1356 msg.Append("heap-sample-item,%s,%d,%d", type, number, bytes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001357 msg.WriteToLogFile();
Steve Block3ce2e202009-11-05 08:53:23 +00001358}
1359
1360
Steve Blocka7e24c12009-10-30 11:49:00 +00001361void Logger::DebugTag(const char* call_site_tag) {
Steve Block44f0eee2011-05-26 01:26:41 +01001362 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001363 Log::MessageBuilder msg(log_);
1364 msg.Append("debug-tag,%s", call_site_tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001365 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001366}
1367
1368
1369void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
Steve Block44f0eee2011-05-26 01:26:41 +01001370 if (!log_->IsEnabled() || !FLAG_log) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001371 StringBuilder s(parameter.length() + 1);
1372 for (int i = 0; i < parameter.length(); ++i) {
1373 s.AddCharacter(static_cast<char>(parameter[i]));
1374 }
1375 char* parameter_string = s.Finalize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001376 Log::MessageBuilder msg(log_);
1377 msg.Append("debug-queue-event,%s,%15.3f,%s", event_type,
1378 base::OS::TimeCurrentMillis(), parameter_string);
Steve Blocka7e24c12009-10-30 11:49:00 +00001379 DeleteArray(parameter_string);
1380 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001381}
1382
1383
Steve Blocka7e24c12009-10-30 11:49:00 +00001384void Logger::TickEvent(TickSample* sample, bool overflow) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001385 if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001386 Log::MessageBuilder msg(log_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001387 msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
1388 msg.AppendAddress(sample->pc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001389 msg.Append(",%ld", static_cast<int>(timer_.Elapsed().InMicroseconds()));
Steve Block44f0eee2011-05-26 01:26:41 +01001390 if (sample->has_external_callback) {
1391 msg.Append(",1,");
Ben Murdoch097c5b22016-05-18 11:27:45 +01001392 msg.AppendAddress(sample->external_callback_entry);
Steve Block44f0eee2011-05-26 01:26:41 +01001393 } else {
1394 msg.Append(",0,");
1395 msg.AppendAddress(sample->tos);
1396 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001397 msg.Append(",%d", static_cast<int>(sample->state));
1398 if (overflow) {
1399 msg.Append(",overflow");
1400 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001401 for (unsigned i = 0; i < sample->frames_count; ++i) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001402 msg.Append(',');
Ben Murdochb0fe1622011-05-05 13:52:32 +01001403 msg.AppendAddress(sample->stack[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001404 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001405 msg.WriteToLogFile();
1406}
1407
1408
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001409void Logger::StopProfiler() {
Steve Block44f0eee2011-05-26 01:26:41 +01001410 if (!log_->IsEnabled()) return;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001411 if (profiler_ != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001412 profiler_->pause();
1413 is_logging_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001414 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001415}
1416
1417
1418// This function can be called when Log's mutex is acquired,
1419// either from main or Profiler's thread.
Steve Block44f0eee2011-05-26 01:26:41 +01001420void Logger::LogFailure() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001421 StopProfiler();
Steve Blocka7e24c12009-10-30 11:49:00 +00001422}
1423
1424
Ben Murdochb0fe1622011-05-05 13:52:32 +01001425class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor {
1426 public:
1427 EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis,
Ben Murdochda12d292016-06-02 14:46:10 +01001428 Handle<AbstractCode>* code_objects,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001429 int* count)
Ben Murdochda12d292016-06-02 14:46:10 +01001430 : sfis_(sfis), code_objects_(code_objects), count_(count) {}
Ben Murdochb0fe1622011-05-05 13:52:32 +01001431
1432 virtual void EnterContext(Context* context) {}
1433 virtual void LeaveContext(Context* context) {}
1434
1435 virtual void VisitFunction(JSFunction* function) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001436 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(function->shared());
1437 Object* maybe_script = sfi->script();
1438 if (maybe_script->IsScript()
1439 && !Script::cast(maybe_script)->HasValidSource()) return;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001440 if (sfis_ != NULL) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001441 sfis_[*count_] = Handle<SharedFunctionInfo>(sfi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001442 }
1443 if (code_objects_ != NULL) {
Ben Murdochda12d292016-06-02 14:46:10 +01001444 DCHECK(function->abstract_code()->kind() ==
1445 AbstractCode::OPTIMIZED_FUNCTION);
1446 code_objects_[*count_] = Handle<AbstractCode>(function->abstract_code());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001447 }
1448 *count_ = *count_ + 1;
1449 }
1450
1451 private:
1452 Handle<SharedFunctionInfo>* sfis_;
Ben Murdochda12d292016-06-02 14:46:10 +01001453 Handle<AbstractCode>* code_objects_;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001454 int* count_;
1455};
1456
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001457static int EnumerateCompiledFunctions(Heap* heap,
1458 Handle<SharedFunctionInfo>* sfis,
Ben Murdochda12d292016-06-02 14:46:10 +01001459 Handle<AbstractCode>* code_objects) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001460 HeapIterator iterator(heap);
1461 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001462 int compiled_funcs_count = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001463
1464 // Iterate the heap to find shared function info objects and record
1465 // the unoptimized code for them.
Leon Clarked91b9f72010-01-27 17:25:45 +00001466 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001467 if (!obj->IsSharedFunctionInfo()) continue;
1468 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
1469 if (sfi->is_compiled()
1470 && (!sfi->script()->IsScript()
1471 || Script::cast(sfi->script())->HasValidSource())) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001472 if (sfis != NULL) {
Steve Block3ce2e202009-11-05 08:53:23 +00001473 sfis[compiled_funcs_count] = Handle<SharedFunctionInfo>(sfi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001474 }
1475 if (code_objects != NULL) {
Ben Murdochda12d292016-06-02 14:46:10 +01001476 code_objects[compiled_funcs_count] =
1477 Handle<AbstractCode>(sfi->abstract_code());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001478 }
Steve Block3ce2e202009-11-05 08:53:23 +00001479 ++compiled_funcs_count;
Steve Blocka7e24c12009-10-30 11:49:00 +00001480 }
1481 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001482
1483 // Iterate all optimized functions in all contexts.
1484 EnumerateOptimizedFunctionsVisitor visitor(sfis,
1485 code_objects,
1486 &compiled_funcs_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001487 Deoptimizer::VisitAllOptimizedFunctions(heap->isolate(), &visitor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001488
Steve Block3ce2e202009-11-05 08:53:23 +00001489 return compiled_funcs_count;
1490}
1491
1492
Steve Blockd0582a62009-12-15 09:54:21 +00001493void Logger::LogCodeObject(Object* object) {
Ben Murdochda12d292016-06-02 14:46:10 +01001494 AbstractCode* code_object = AbstractCode::cast(object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001495 LogEventsAndTags tag = Logger::STUB_TAG;
1496 const char* description = "Unknown code from the snapshot";
1497 switch (code_object->kind()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001498 case AbstractCode::FUNCTION:
1499 case AbstractCode::INTERPRETED_FUNCTION:
1500 case AbstractCode::OPTIMIZED_FUNCTION:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001501 return; // We log this later using LogCompiledFunctions.
Ben Murdochda12d292016-06-02 14:46:10 +01001502 case AbstractCode::BYTECODE_HANDLER:
1503 return; // We log it later by walking the dispatch table.
1504 case AbstractCode::BINARY_OP_IC: // fall through
1505 case AbstractCode::COMPARE_IC: // fall through
1506 case AbstractCode::TO_BOOLEAN_IC: // fall through
1507
1508 case AbstractCode::STUB:
1509 description =
1510 CodeStub::MajorName(CodeStub::GetMajorKey(code_object->GetCode()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001511 if (description == NULL)
1512 description = "A stub from the snapshot";
1513 tag = Logger::STUB_TAG;
1514 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001515 case AbstractCode::REGEXP:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001516 description = "Regular expression code";
1517 tag = Logger::REG_EXP_TAG;
1518 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001519 case AbstractCode::BUILTIN:
1520 description =
1521 isolate_->builtins()->name(code_object->GetCode()->builtin_index());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001522 tag = Logger::BUILTIN_TAG;
1523 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001524 case AbstractCode::HANDLER:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001525 description = "An IC handler from the snapshot";
1526 tag = Logger::HANDLER_TAG;
1527 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001528 case AbstractCode::KEYED_LOAD_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001529 description = "A keyed load IC from the snapshot";
1530 tag = Logger::KEYED_LOAD_IC_TAG;
1531 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001532 case AbstractCode::LOAD_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001533 description = "A load IC from the snapshot";
1534 tag = Logger::LOAD_IC_TAG;
1535 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001536 case AbstractCode::CALL_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001537 description = "A call IC from the snapshot";
1538 tag = Logger::CALL_IC_TAG;
1539 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001540 case AbstractCode::STORE_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001541 description = "A store IC from the snapshot";
1542 tag = Logger::STORE_IC_TAG;
1543 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001544 case AbstractCode::KEYED_STORE_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001545 description = "A keyed store IC from the snapshot";
1546 tag = Logger::KEYED_STORE_IC_TAG;
1547 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001548 case AbstractCode::WASM_FUNCTION:
1549 description = "A Wasm function";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001550 tag = Logger::STUB_TAG;
1551 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001552 case AbstractCode::JS_TO_WASM_FUNCTION:
1553 description = "A JavaScript to Wasm adapter";
1554 tag = Logger::STUB_TAG;
1555 break;
1556 case AbstractCode::WASM_TO_JS_FUNCTION:
1557 description = "A Wasm to JavaScript adapter";
1558 tag = Logger::STUB_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001559 break;
Steve Blockd0582a62009-12-15 09:54:21 +00001560 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001561 PROFILE(isolate_, CodeCreateEvent(tag, code_object, description));
Ben Murdochf87a2032010-10-22 12:50:53 +01001562}
1563
1564
Andrei Popescu31002712010-02-23 13:46:05 +00001565void Logger::LogCodeObjects() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001566 Heap* heap = isolate_->heap();
1567 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001568 "Logger::LogCodeObjects");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569 HeapIterator iterator(heap);
1570 DisallowHeapAllocation no_gc;
Andrei Popescu31002712010-02-23 13:46:05 +00001571 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1572 if (obj->IsCode()) LogCodeObject(obj);
Ben Murdochda12d292016-06-02 14:46:10 +01001573 if (obj->IsBytecodeArray()) LogCodeObject(obj);
Andrei Popescu31002712010-02-23 13:46:05 +00001574 }
1575}
1576
Ben Murdochda12d292016-06-02 14:46:10 +01001577void Logger::LogBytecodeHandlers() {
1578 if (!FLAG_ignition) return;
1579
1580 interpreter::Interpreter* interpreter = isolate_->interpreter();
1581 const int last_index = static_cast<int>(interpreter::Bytecode::kLast);
1582 for (auto operand_scale = interpreter::OperandScale::kSingle;
1583 operand_scale <= interpreter::OperandScale::kMaxValid;
1584 operand_scale =
1585 interpreter::Bytecodes::NextOperandScale(operand_scale)) {
1586 for (int index = 0; index <= last_index; ++index) {
1587 interpreter::Bytecode bytecode = interpreter::Bytecodes::FromByte(index);
1588 if (interpreter::Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) {
1589 Code* code = interpreter->GetBytecodeHandler(bytecode, operand_scale);
1590 std::string bytecode_name =
1591 interpreter::Bytecodes::ToString(bytecode, operand_scale);
1592 CodeCreateEvent(Logger::BYTECODE_HANDLER_TAG, AbstractCode::cast(code),
1593 bytecode_name.c_str());
1594 }
1595 }
1596 }
1597}
Andrei Popescu31002712010-02-23 13:46:05 +00001598
Ben Murdoch589d6972011-11-30 16:04:58 +00001599void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
Ben Murdochda12d292016-06-02 14:46:10 +01001600 Handle<AbstractCode> code) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001601 Handle<String> func_name(shared->DebugName());
1602 if (shared->script()->IsScript()) {
1603 Handle<Script> script(Script::cast(shared->script()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001604 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
1605 int column_num =
1606 Script::GetColumnNumber(script, shared->start_position()) + 1;
Ben Murdoch589d6972011-11-30 16:04:58 +00001607 if (script->name()->IsString()) {
1608 Handle<String> script_name(String::cast(script->name()));
Ben Murdoch589d6972011-11-30 16:04:58 +00001609 if (line_num > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001610 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001611 CodeCreateEvent(
1612 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613 *code, *shared, NULL,
1614 *script_name, line_num, column_num));
Ben Murdoch589d6972011-11-30 16:04:58 +00001615 } else {
1616 // Can't distinguish eval and script here, so always use Script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001617 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001618 CodeCreateEvent(
1619 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001620 *code, *shared, NULL, *script_name));
Ben Murdoch589d6972011-11-30 16:04:58 +00001621 }
1622 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001623 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001624 CodeCreateEvent(
1625 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001626 *code, *shared, NULL,
1627 isolate_->heap()->empty_string(), line_num, column_num));
Ben Murdoch589d6972011-11-30 16:04:58 +00001628 }
1629 } else if (shared->IsApiFunction()) {
1630 // API function.
1631 FunctionTemplateInfo* fun_data = shared->get_api_func_data();
1632 Object* raw_call_data = fun_data->call_code();
1633 if (!raw_call_data->IsUndefined()) {
1634 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1635 Object* callback_obj = call_data->callback();
1636 Address entry_point = v8::ToCData<Address>(callback_obj);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001637#if USES_FUNCTION_DESCRIPTORS
1638 entry_point = *FUNCTION_ENTRYPOINT_ADDRESS(entry_point);
1639#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001640 PROFILE(isolate_, CallbackEvent(*func_name, entry_point));
Ben Murdoch589d6972011-11-30 16:04:58 +00001641 }
1642 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001643 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001644 CodeCreateEvent(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001645 Logger::LAZY_COMPILE_TAG, *code, *shared, NULL, *func_name));
Ben Murdoch589d6972011-11-30 16:04:58 +00001646 }
1647}
1648
1649
Steve Block3ce2e202009-11-05 08:53:23 +00001650void Logger::LogCompiledFunctions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001651 Heap* heap = isolate_->heap();
1652 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001653 "Logger::LogCompiledFunctions");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001654 HandleScope scope(isolate_);
1655 const int compiled_funcs_count = EnumerateCompiledFunctions(heap, NULL, NULL);
Kristian Monsen25f61362010-05-21 11:50:48 +01001656 ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
Ben Murdochda12d292016-06-02 14:46:10 +01001657 ScopedVector<Handle<AbstractCode> > code_objects(compiled_funcs_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001658 EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00001659
1660 // During iteration, there can be heap allocation due to
1661 // GetScriptLineNumber call.
1662 for (int i = 0; i < compiled_funcs_count; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001663 if (code_objects[i].is_identical_to(isolate_->builtins()->CompileLazy()))
Steve Block44f0eee2011-05-26 01:26:41 +01001664 continue;
Ben Murdoch589d6972011-11-30 16:04:58 +00001665 LogExistingFunction(sfis[i], code_objects[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001666 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001667}
1668
Steve Blockd0582a62009-12-15 09:54:21 +00001669
1670void Logger::LogAccessorCallbacks() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001671 Heap* heap = isolate_->heap();
1672 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001673 "Logger::LogAccessorCallbacks");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001674 HeapIterator iterator(heap);
1675 DisallowHeapAllocation no_gc;
Leon Clarked91b9f72010-01-27 17:25:45 +00001676 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001677 if (!obj->IsAccessorInfo()) continue;
1678 AccessorInfo* ai = AccessorInfo::cast(obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001679 if (!ai->name()->IsName()) continue;
Steve Blockd0582a62009-12-15 09:54:21 +00001680 Address getter_entry = v8::ToCData<Address>(ai->getter());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001681 Name* name = Name::cast(ai->name());
Steve Blockd0582a62009-12-15 09:54:21 +00001682 if (getter_entry != 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001683#if USES_FUNCTION_DESCRIPTORS
1684 getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(getter_entry);
1685#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001686 PROFILE(isolate_, GetterCallbackEvent(name, getter_entry));
Steve Blockd0582a62009-12-15 09:54:21 +00001687 }
1688 Address setter_entry = v8::ToCData<Address>(ai->setter());
1689 if (setter_entry != 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001690#if USES_FUNCTION_DESCRIPTORS
1691 setter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(setter_entry);
1692#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001693 PROFILE(isolate_, SetterCallbackEvent(name, setter_entry));
Steve Blockd0582a62009-12-15 09:54:21 +00001694 }
1695 }
1696}
1697
Steve Blocka7e24c12009-10-30 11:49:00 +00001698
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001699static void AddIsolateIdIfNeeded(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001700 Isolate* isolate) {
1701 if (FLAG_logfile_per_isolate) os << "isolate-" << isolate << "-";
1702}
1703
1704
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001705static void PrepareLogFileName(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001706 Isolate* isolate, const char* file_name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001707 int dir_separator_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001708 for (const char* p = file_name; *p; p++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001709 if (base::OS::isDirectorySeparator(*p)) dir_separator_count++;
1710 }
1711
1712 for (const char* p = file_name; *p; p++) {
1713 if (dir_separator_count == 0) {
1714 AddIsolateIdIfNeeded(os, isolate);
1715 dir_separator_count--;
1716 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001717 if (*p == '%') {
1718 p++;
1719 switch (*p) {
1720 case '\0':
1721 // If there's a % at the end of the string we back up
1722 // one character so we can escape the loop properly.
1723 p--;
1724 break;
1725 case 'p':
1726 os << base::OS::GetCurrentProcessId();
1727 break;
1728 case 't':
1729 // %t expands to the current time in milliseconds.
1730 os << static_cast<int64_t>(base::OS::TimeCurrentMillis());
1731 break;
1732 case '%':
1733 // %% expands (contracts really) to %.
1734 os << '%';
1735 break;
1736 default:
1737 // All other %'s expand to themselves.
1738 os << '%' << *p;
1739 break;
1740 }
1741 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001742 if (base::OS::isDirectorySeparator(*p)) dir_separator_count--;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001743 os << *p;
1744 }
1745 }
1746}
1747
1748
1749bool Logger::SetUp(Isolate* isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +01001750 // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
1751 if (is_initialized_) return true;
1752 is_initialized_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001753
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001754 std::ostringstream log_file_name;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001755 PrepareLogFileName(log_file_name, isolate, FLAG_logfile);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001756 log_->Initialize(log_file_name.str().c_str());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001757
1758
1759 if (FLAG_perf_basic_prof) {
1760 perf_basic_logger_ = new PerfBasicLogger();
1761 addCodeEventListener(perf_basic_logger_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001762 }
1763
Ben Murdochda12d292016-06-02 14:46:10 +01001764 if (FLAG_perf_prof) {
1765 perf_jit_logger_ = new PerfJitLogger();
1766 addCodeEventListener(perf_jit_logger_);
1767 }
1768
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001769 if (FLAG_ll_prof) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001770 ll_logger_ = new LowLevelLogger(log_file_name.str().c_str());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001771 addCodeEventListener(ll_logger_);
1772 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001773
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001774 ticker_ = new Ticker(isolate, kSamplingIntervalMs);
1775
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001776 if (Log::InitLogAtStart()) {
1777 is_logging_ = true;
Steve Block6ded16b2010-05-10 14:33:55 +01001778 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001779
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001780 if (FLAG_log_internal_timer_events || FLAG_prof_cpp) timer_.Start();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001781
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001782 if (FLAG_prof_cpp) {
Steve Block44f0eee2011-05-26 01:26:41 +01001783 profiler_ = new Profiler(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001784 is_logging_ = true;
1785 profiler_->Engage();
Steve Blocka7e24c12009-10-30 11:49:00 +00001786 }
1787
Steve Blocka7e24c12009-10-30 11:49:00 +00001788 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001789}
1790
1791
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001792void Logger::SetCodeEventHandler(uint32_t options,
1793 JitCodeEventHandler event_handler) {
1794 if (jit_logger_) {
1795 removeCodeEventListener(jit_logger_);
1796 delete jit_logger_;
1797 jit_logger_ = NULL;
1798 }
1799
1800 if (event_handler) {
1801 jit_logger_ = new JitLogger(event_handler);
1802 addCodeEventListener(jit_logger_);
1803 if (options & kJitCodeEventEnumExisting) {
1804 HandleScope scope(isolate_);
1805 LogCodeObjects();
1806 LogCompiledFunctions();
1807 }
1808 }
1809}
1810
1811
Steve Block44f0eee2011-05-26 01:26:41 +01001812Sampler* Logger::sampler() {
1813 return ticker_;
1814}
1815
1816
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001817FILE* Logger::TearDown() {
1818 if (!is_initialized_) return NULL;
Steve Block44f0eee2011-05-26 01:26:41 +01001819 is_initialized_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001820
1821 // Stop the profiler before closing the file.
1822 if (profiler_ != NULL) {
1823 profiler_->Disengage();
1824 delete profiler_;
1825 profiler_ = NULL;
1826 }
1827
Steve Blocka7e24c12009-10-30 11:49:00 +00001828 delete ticker_;
1829 ticker_ = NULL;
1830
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001831 if (perf_basic_logger_) {
1832 removeCodeEventListener(perf_basic_logger_);
1833 delete perf_basic_logger_;
1834 perf_basic_logger_ = NULL;
1835 }
1836
Ben Murdochda12d292016-06-02 14:46:10 +01001837 if (perf_jit_logger_) {
1838 removeCodeEventListener(perf_jit_logger_);
1839 delete perf_jit_logger_;
1840 perf_jit_logger_ = NULL;
1841 }
1842
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001843 if (ll_logger_) {
1844 removeCodeEventListener(ll_logger_);
1845 delete ll_logger_;
1846 ll_logger_ = NULL;
1847 }
1848
1849 if (jit_logger_) {
1850 removeCodeEventListener(jit_logger_);
1851 delete jit_logger_;
1852 jit_logger_ = NULL;
1853 }
1854
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001855 return log_->Close();
Steve Blocka7e24c12009-10-30 11:49:00 +00001856}
1857
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001858} // namespace internal
1859} // namespace v8