blob: 97acea9c1fd82f2b5fc5074815b46e886f1e6eac [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 Murdochc5610432016-08-08 18:44:38 +0100183 SharedFunctionInfo* shared, Name* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 name_buffer_->Init(tag);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185 name_buffer_->AppendBytes(ComputeMarker(shared, code));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186 name_buffer_->AppendName(name);
187 LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
188}
189
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100191 AbstractCode* code,
Ben Murdochc5610432016-08-08 18:44:38 +0100192 SharedFunctionInfo* shared, Name* source,
Ben Murdochda12d292016-06-02 14:46:10 +0100193 int line, int column) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 name_buffer_->Init(tag);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 name_buffer_->AppendBytes(ComputeMarker(shared, code));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 name_buffer_->AppendString(shared->DebugName());
197 name_buffer_->AppendByte(' ');
198 if (source->IsString()) {
199 name_buffer_->AppendString(String::cast(source));
200 } else {
201 name_buffer_->AppendBytes("symbol(hash ");
202 name_buffer_->AppendHex(Name::cast(source)->Hash());
203 name_buffer_->AppendByte(')');
204 }
205 name_buffer_->AppendByte(':');
206 name_buffer_->AppendInt(line);
207 LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
208}
209
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100211 AbstractCode* code, int args_count) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 name_buffer_->Init(tag);
213 name_buffer_->AppendInt(args_count);
214 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
215}
216
Ben Murdochda12d292016-06-02 14:46:10 +0100217void CodeEventLogger::RegExpCodeCreateEvent(AbstractCode* code,
218 String* source) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 name_buffer_->Init(Logger::REG_EXP_TAG);
220 name_buffer_->AppendString(source);
221 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
222}
223
224
225// Linux perf tool logging support
226class PerfBasicLogger : public CodeEventLogger {
227 public:
228 PerfBasicLogger();
Ben Murdochda12d292016-06-02 14:46:10 +0100229 ~PerfBasicLogger() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230
Ben Murdochda12d292016-06-02 14:46:10 +0100231 void CodeMoveEvent(AbstractCode* from, Address to) override {}
232 void CodeDisableOptEvent(AbstractCode* code,
233 SharedFunctionInfo* shared) override {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234
235 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100236 void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo* shared,
237 const char* name, int length) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238
239 // Extension added to V8 log file name to get the low-level log name.
240 static const char kFilenameFormatString[];
241 static const int kFilenameBufferPadding;
242
243 // File buffer size of the low-level log. We don't use the default to
244 // minimize the associated overhead.
245 static const int kLogBufferSize = 2 * MB;
246
247 FILE* perf_output_handle_;
248};
249
250const char PerfBasicLogger::kFilenameFormatString[] = "/tmp/perf-%d.map";
251// Extra space for the PID in the filename
252const int PerfBasicLogger::kFilenameBufferPadding = 16;
253
254PerfBasicLogger::PerfBasicLogger()
255 : perf_output_handle_(NULL) {
256 // Open the perf JIT dump file.
257 int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
258 ScopedVector<char> perf_dump_name(bufferSize);
259 int size = SNPrintF(
260 perf_dump_name,
261 kFilenameFormatString,
262 base::OS::GetCurrentProcessId());
263 CHECK_NE(size, -1);
264 perf_output_handle_ =
265 base::OS::FOpen(perf_dump_name.start(), base::OS::LogFileOpenMode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266 CHECK_NOT_NULL(perf_output_handle_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267 setvbuf(perf_output_handle_, NULL, _IOFBF, kLogBufferSize);
268}
269
270
271PerfBasicLogger::~PerfBasicLogger() {
272 fclose(perf_output_handle_);
273 perf_output_handle_ = NULL;
274}
275
Ben Murdochda12d292016-06-02 14:46:10 +0100276void PerfBasicLogger::LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
277 const char* name, int length) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 if (FLAG_perf_basic_prof_only_functions &&
Ben Murdochda12d292016-06-02 14:46:10 +0100279 (code->kind() != AbstractCode::FUNCTION &&
280 code->kind() != AbstractCode::INTERPRETED_FUNCTION &&
281 code->kind() != AbstractCode::OPTIMIZED_FUNCTION)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 return;
283 }
284
Ben Murdochc5610432016-08-08 18:44:38 +0100285 // Linux perf expects hex literals without a leading 0x, while some
286 // implementations of printf might prepend one when using the %p format
287 // for pointers, leading to wrongly formatted JIT symbols maps.
288 //
289 // Instead, we use V8PRIxPTR format string and cast pointer to uintpr_t,
290 // so that we have control over the exact output format.
291 base::OS::FPrint(perf_output_handle_, "%" V8PRIxPTR " %x %.*s\n",
292 reinterpret_cast<uintptr_t>(code->instruction_start()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 code->instruction_size(), length, name);
294}
295
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000296// Low-level logging support.
297#define LL_LOG(Call) if (ll_logger_) ll_logger_->Call;
298
299class LowLevelLogger : public CodeEventLogger {
300 public:
301 explicit LowLevelLogger(const char* file_name);
Ben Murdochda12d292016-06-02 14:46:10 +0100302 ~LowLevelLogger() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303
Ben Murdochda12d292016-06-02 14:46:10 +0100304 void CodeMoveEvent(AbstractCode* from, Address to) override;
305 void CodeDisableOptEvent(AbstractCode* code,
306 SharedFunctionInfo* shared) override {}
307 void SnapshotPositionEvent(HeapObject* obj, int pos);
308 void CodeMovingGCEvent() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000309
310 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100311 void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo* shared,
312 const char* name, int length) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000313
314 // Low-level profiling event structures.
315 struct CodeCreateStruct {
316 static const char kTag = 'C';
317
318 int32_t name_size;
319 Address code_address;
320 int32_t code_size;
321 };
322
323
324 struct CodeMoveStruct {
325 static const char kTag = 'M';
326
327 Address from_address;
328 Address to_address;
329 };
330
331
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 static const char kCodeMovingGCTag = 'G';
333
334
335 // Extension added to V8 log file name to get the low-level log name.
336 static const char kLogExt[];
337
338 // File buffer size of the low-level log. We don't use the default to
339 // minimize the associated overhead.
340 static const int kLogBufferSize = 2 * MB;
341
342 void LogCodeInfo();
343 void LogWriteBytes(const char* bytes, int size);
344
345 template <typename T>
346 void LogWriteStruct(const T& s) {
347 char tag = T::kTag;
348 LogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag));
349 LogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s));
350 }
351
352 FILE* ll_output_handle_;
353};
354
355const char LowLevelLogger::kLogExt[] = ".ll";
356
357LowLevelLogger::LowLevelLogger(const char* name)
358 : ll_output_handle_(NULL) {
359 // Open the low-level log file.
360 size_t len = strlen(name);
361 ScopedVector<char> ll_name(static_cast<int>(len + sizeof(kLogExt)));
362 MemCopy(ll_name.start(), name, len);
363 MemCopy(ll_name.start() + len, kLogExt, sizeof(kLogExt));
364 ll_output_handle_ =
365 base::OS::FOpen(ll_name.start(), base::OS::LogFileOpenMode);
366 setvbuf(ll_output_handle_, NULL, _IOFBF, kLogBufferSize);
367
368 LogCodeInfo();
369}
370
371
372LowLevelLogger::~LowLevelLogger() {
373 fclose(ll_output_handle_);
374 ll_output_handle_ = NULL;
375}
376
377
378void LowLevelLogger::LogCodeInfo() {
379#if V8_TARGET_ARCH_IA32
380 const char arch[] = "ia32";
381#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
382 const char arch[] = "x64";
383#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
384 const char arch[] = "x32";
385#elif V8_TARGET_ARCH_ARM
386 const char arch[] = "arm";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000387#elif V8_TARGET_ARCH_PPC
388 const char arch[] = "ppc";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000389#elif V8_TARGET_ARCH_MIPS
390 const char arch[] = "mips";
391#elif V8_TARGET_ARCH_X87
392 const char arch[] = "x87";
393#elif V8_TARGET_ARCH_ARM64
394 const char arch[] = "arm64";
Ben Murdochda12d292016-06-02 14:46:10 +0100395#elif V8_TARGET_ARCH_S390
396 const char arch[] = "s390";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397#else
398 const char arch[] = "unknown";
399#endif
400 LogWriteBytes(arch, sizeof(arch));
401}
402
Ben Murdochda12d292016-06-02 14:46:10 +0100403void LowLevelLogger::LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
404 const char* name, int length) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000405 CodeCreateStruct event;
406 event.name_size = length;
407 event.code_address = code->instruction_start();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000408 event.code_size = code->instruction_size();
409 LogWriteStruct(event);
410 LogWriteBytes(name, length);
411 LogWriteBytes(
412 reinterpret_cast<const char*>(code->instruction_start()),
413 code->instruction_size());
414}
415
Ben Murdochda12d292016-06-02 14:46:10 +0100416void LowLevelLogger::CodeMoveEvent(AbstractCode* from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000417 CodeMoveStruct event;
Ben Murdochda12d292016-06-02 14:46:10 +0100418 event.from_address = from->instruction_start();
419 size_t header_size = from->instruction_start() - from->address();
420 event.to_address = to + header_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000421 LogWriteStruct(event);
422}
423
424
425void LowLevelLogger::LogWriteBytes(const char* bytes, int size) {
426 size_t rv = fwrite(bytes, 1, size, ll_output_handle_);
427 DCHECK(static_cast<size_t>(size) == rv);
428 USE(rv);
429}
430
431
432void LowLevelLogger::CodeMovingGCEvent() {
433 const char tag = kCodeMovingGCTag;
434
435 LogWriteBytes(&tag, sizeof(tag));
436}
437
438
439#define JIT_LOG(Call) if (jit_logger_) jit_logger_->Call;
440
441
442class JitLogger : public CodeEventLogger {
443 public:
444 explicit JitLogger(JitCodeEventHandler code_event_handler);
445
Ben Murdochda12d292016-06-02 14:46:10 +0100446 void CodeMoveEvent(AbstractCode* from, Address to) override;
447 void CodeDisableOptEvent(AbstractCode* code,
448 SharedFunctionInfo* shared) override {}
449 void AddCodeLinePosInfoEvent(void* jit_handler_data, int pc_offset,
450 int position,
451 JitCodeEvent::PositionType position_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000452
453 void* StartCodePosInfoEvent();
Ben Murdochda12d292016-06-02 14:46:10 +0100454 void EndCodePosInfoEvent(AbstractCode* code, void* jit_handler_data);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000455
456 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100457 void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo* shared,
458 const char* name, int length) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000459
460 JitCodeEventHandler code_event_handler_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461 base::Mutex logger_mutex_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000462};
463
464
465JitLogger::JitLogger(JitCodeEventHandler code_event_handler)
466 : code_event_handler_(code_event_handler) {
467}
468
Ben Murdochda12d292016-06-02 14:46:10 +0100469void JitLogger::LogRecordedBuffer(AbstractCode* code,
470 SharedFunctionInfo* shared, const char* name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000471 int length) {
472 JitCodeEvent event;
473 memset(&event, 0, sizeof(event));
474 event.type = JitCodeEvent::CODE_ADDED;
475 event.code_start = code->instruction_start();
476 event.code_len = code->instruction_size();
477 Handle<SharedFunctionInfo> shared_function_handle;
478 if (shared && shared->script()->IsScript()) {
479 shared_function_handle = Handle<SharedFunctionInfo>(shared);
480 }
481 event.script = ToApiHandle<v8::UnboundScript>(shared_function_handle);
482 event.name.str = name;
483 event.name.len = length;
484 code_event_handler_(&event);
485}
486
Ben Murdochda12d292016-06-02 14:46:10 +0100487void JitLogger::CodeMoveEvent(AbstractCode* from, Address to) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 base::LockGuard<base::Mutex> guard(&logger_mutex_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000489
490 JitCodeEvent event;
491 event.type = JitCodeEvent::CODE_MOVED;
Ben Murdochda12d292016-06-02 14:46:10 +0100492 event.code_start = from->instruction_start();
493 event.code_len = from->instruction_size();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494
495 // Calculate the header size.
Ben Murdochda12d292016-06-02 14:46:10 +0100496 const size_t header_size = from->instruction_start() - from->address();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000497
498 // Calculate the new start address of the instructions.
Ben Murdochda12d292016-06-02 14:46:10 +0100499 event.new_code_start = to + header_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000500
501 code_event_handler_(&event);
502}
503
504void JitLogger::AddCodeLinePosInfoEvent(
505 void* jit_handler_data,
506 int pc_offset,
507 int position,
508 JitCodeEvent::PositionType position_type) {
509 JitCodeEvent event;
510 memset(&event, 0, sizeof(event));
511 event.type = JitCodeEvent::CODE_ADD_LINE_POS_INFO;
512 event.user_data = jit_handler_data;
513 event.line_info.offset = pc_offset;
514 event.line_info.pos = position;
515 event.line_info.position_type = position_type;
516
517 code_event_handler_(&event);
518}
519
520
521void* JitLogger::StartCodePosInfoEvent() {
522 JitCodeEvent event;
523 memset(&event, 0, sizeof(event));
524 event.type = JitCodeEvent::CODE_START_LINE_INFO_RECORDING;
525
526 code_event_handler_(&event);
527 return event.user_data;
528}
529
Ben Murdochda12d292016-06-02 14:46:10 +0100530void JitLogger::EndCodePosInfoEvent(AbstractCode* code,
531 void* jit_handler_data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 JitCodeEvent event;
533 memset(&event, 0, sizeof(event));
534 event.type = JitCodeEvent::CODE_END_LINE_INFO_RECORDING;
535 event.code_start = code->instruction_start();
536 event.user_data = jit_handler_data;
537
538 code_event_handler_(&event);
539}
540
541
542// The Profiler samples pc and sp values for the main thread.
543// Each sample is appended to a circular buffer.
544// An independent thread removes data and writes it to the log.
545// This design minimizes the time spent in the sampler.
546//
547class Profiler: public base::Thread {
548 public:
549 explicit Profiler(Isolate* isolate);
550 void Engage();
551 void Disengage();
552
553 // Inserts collected profiling data into buffer.
554 void Insert(TickSample* sample) {
555 if (paused_)
556 return;
557
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400558 if (Succ(head_) == static_cast<int>(base::NoBarrier_Load(&tail_))) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559 overflow_ = true;
560 } else {
561 buffer_[head_] = *sample;
562 head_ = Succ(head_);
563 buffer_semaphore_.Signal(); // Tell we have an element.
564 }
565 }
566
567 virtual void Run();
568
569 // Pause and Resume TickSample data collection.
570 void pause() { paused_ = true; }
571 void resume() { paused_ = false; }
572
573 private:
574 // Waits for a signal and removes profiling data.
575 bool Remove(TickSample* sample) {
576 buffer_semaphore_.Wait(); // Wait for an element.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400577 *sample = buffer_[base::NoBarrier_Load(&tail_)];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578 bool result = overflow_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400579 base::NoBarrier_Store(&tail_, static_cast<base::Atomic32>(
580 Succ(base::NoBarrier_Load(&tail_))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000581 overflow_ = false;
582 return result;
583 }
584
585 // Returns the next index in the cyclic buffer.
586 int Succ(int index) { return (index + 1) % kBufferSize; }
587
588 Isolate* isolate_;
589 // Cyclic buffer for communicating profiling samples
590 // between the signal handler and the worker thread.
591 static const int kBufferSize = 128;
592 TickSample buffer_[kBufferSize]; // Buffer storage.
593 int head_; // Index to the buffer head.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400594 base::Atomic32 tail_; // Index to the buffer tail.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595 bool overflow_; // Tell whether a buffer overflow has occurred.
596 // Sempahore used for buffer synchronization.
597 base::Semaphore buffer_semaphore_;
598
599 // Tells whether profiler is engaged, that is, processing thread is stated.
600 bool engaged_;
601
602 // Tells whether worker thread should continue running.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400603 base::Atomic32 running_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000604
605 // Tells whether we are currently recording tick samples.
606 bool paused_;
607};
608
609
610//
611// Ticker used to provide ticks to the profiler and the sliding state
612// window.
613//
614class Ticker: public Sampler {
615 public:
616 Ticker(Isolate* isolate, int interval):
617 Sampler(isolate, interval),
618 profiler_(NULL) {}
619
620 ~Ticker() { if (IsActive()) Stop(); }
621
622 virtual void Tick(TickSample* sample) {
623 if (profiler_) profiler_->Insert(sample);
624 }
625
626 void SetProfiler(Profiler* profiler) {
627 DCHECK(profiler_ == NULL);
628 profiler_ = profiler;
629 IncreaseProfilingDepth();
630 if (!IsActive()) Start();
631 }
632
633 void ClearProfiler() {
634 profiler_ = NULL;
635 if (IsActive()) Stop();
636 DecreaseProfilingDepth();
637 }
638
639 private:
640 Profiler* profiler_;
641};
642
643
644//
645// Profiler implementation.
646//
647Profiler::Profiler(Isolate* isolate)
648 : base::Thread(Options("v8:Profiler")),
649 isolate_(isolate),
650 head_(0),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000651 overflow_(false),
652 buffer_semaphore_(0),
653 engaged_(false),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400654 paused_(false) {
655 base::NoBarrier_Store(&tail_, 0);
656 base::NoBarrier_Store(&running_, 0);
657}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000658
659
660void Profiler::Engage() {
661 if (engaged_) return;
662 engaged_ = true;
663
664 std::vector<base::OS::SharedLibraryAddress> addresses =
665 base::OS::GetSharedLibraryAddresses();
666 for (size_t i = 0; i < addresses.size(); ++i) {
Ben Murdochc5610432016-08-08 18:44:38 +0100667 LOG(isolate_,
668 SharedLibraryEvent(addresses[i].library_path, addresses[i].start,
669 addresses[i].end, addresses[i].aslr_slide));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000670 }
671
672 // Start thread processing the profiler buffer.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400673 base::NoBarrier_Store(&running_, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000674 Start();
675
676 // Register to get ticks.
677 Logger* logger = isolate_->logger();
678 logger->ticker_->SetProfiler(this);
679
680 logger->ProfilerBeginEvent();
681}
682
683
684void Profiler::Disengage() {
685 if (!engaged_) return;
686
687 // Stop receiving ticks.
688 isolate_->logger()->ticker_->ClearProfiler();
689
690 // Terminate the worker thread by setting running_ to false,
691 // inserting a fake element in the queue and then wait for
692 // the thread to terminate.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400693 base::NoBarrier_Store(&running_, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000694 TickSample sample;
695 // Reset 'paused_' flag, otherwise semaphore may not be signalled.
696 resume();
697 Insert(&sample);
698 Join();
699
700 LOG(isolate_, UncheckedStringEvent("profiler", "end"));
701}
702
703
704void Profiler::Run() {
705 TickSample sample;
706 bool overflow = Remove(&sample);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400707 while (base::NoBarrier_Load(&running_)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000708 LOG(isolate_, TickEvent(&sample, overflow));
709 overflow = Remove(&sample);
710 }
711}
712
713
714//
715// Logger class implementation.
716//
717
718Logger::Logger(Isolate* isolate)
Ben Murdochda12d292016-06-02 14:46:10 +0100719 : isolate_(isolate),
720 ticker_(NULL),
721 profiler_(NULL),
722 log_events_(NULL),
723 is_logging_(false),
724 log_(new Log(this)),
725 perf_basic_logger_(NULL),
726 perf_jit_logger_(NULL),
727 ll_logger_(NULL),
728 jit_logger_(NULL),
729 listeners_(5),
730 is_initialized_(false) {}
Ben Murdoch257744e2011-11-30 15:57:28 +0000731
Steve Block44f0eee2011-05-26 01:26:41 +0100732Logger::~Logger() {
733 delete log_;
734}
Steve Blocka7e24c12009-10-30 11:49:00 +0000735
Ben Murdoch257744e2011-11-30 15:57:28 +0000736
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737void Logger::addCodeEventListener(CodeEventListener* listener) {
738 DCHECK(!hasCodeEventListener(listener));
739 listeners_.Add(listener);
740}
741
742
743void Logger::removeCodeEventListener(CodeEventListener* listener) {
744 DCHECK(hasCodeEventListener(listener));
745 listeners_.RemoveElement(listener);
746}
747
748
749bool Logger::hasCodeEventListener(CodeEventListener* listener) {
750 return listeners_.Contains(listener);
751}
Steve Blocka7e24c12009-10-30 11:49:00 +0000752
753
754void Logger::ProfilerBeginEvent() {
Steve Block44f0eee2011-05-26 01:26:41 +0100755 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000756 Log::MessageBuilder msg(log_);
757 msg.Append("profiler,\"begin\",%d", kSamplingIntervalMs);
Steve Blocka7e24c12009-10-30 11:49:00 +0000758 msg.WriteToLogFile();
759}
760
Steve Blocka7e24c12009-10-30 11:49:00 +0000761
Steve Blocka7e24c12009-10-30 11:49:00 +0000762void Logger::StringEvent(const char* name, const char* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000763 if (FLAG_log) UncheckedStringEvent(name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000764}
765
766
Steve Blocka7e24c12009-10-30 11:49:00 +0000767void Logger::UncheckedStringEvent(const char* name, const char* value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100768 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000769 Log::MessageBuilder msg(log_);
770 msg.Append("%s,\"%s\"", name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000771 msg.WriteToLogFile();
772}
Steve Blocka7e24c12009-10-30 11:49:00 +0000773
774
775void Logger::IntEvent(const char* name, int value) {
Steve Block6ded16b2010-05-10 14:33:55 +0100776 if (FLAG_log) UncheckedIntEvent(name, value);
Steve Block6ded16b2010-05-10 14:33:55 +0100777}
778
779
Ben Murdochf87a2032010-10-22 12:50:53 +0100780void Logger::IntPtrTEvent(const char* name, intptr_t value) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100781 if (FLAG_log) UncheckedIntPtrTEvent(name, value);
Ben Murdochf87a2032010-10-22 12:50:53 +0100782}
783
784
Steve Block6ded16b2010-05-10 14:33:55 +0100785void Logger::UncheckedIntEvent(const char* name, int value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100786 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000787 Log::MessageBuilder msg(log_);
788 msg.Append("%s,%d", name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000789 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000790}
791
792
Ben Murdochf87a2032010-10-22 12:50:53 +0100793void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100794 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000795 Log::MessageBuilder msg(log_);
Ben Murdochc5610432016-08-08 18:44:38 +0100796 msg.Append("%s,%" V8PRIdPTR, name, value);
Ben Murdochf87a2032010-10-22 12:50:53 +0100797 msg.WriteToLogFile();
798}
Ben Murdochf87a2032010-10-22 12:50:53 +0100799
800
Steve Blocka7e24c12009-10-30 11:49:00 +0000801void Logger::HandleEvent(const char* name, Object** location) {
Steve Block44f0eee2011-05-26 01:26:41 +0100802 if (!log_->IsEnabled() || !FLAG_log_handles) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000803 Log::MessageBuilder msg(log_);
Ben Murdochc5610432016-08-08 18:44:38 +0100804 msg.Append("%s,%p", name, location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000805 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000806}
807
808
Steve Blocka7e24c12009-10-30 11:49:00 +0000809// ApiEvent is private so all the calls come from the Logger class. It is the
810// caller's responsibility to ensure that log is enabled and that
811// FLAG_log_api is true.
812void Logger::ApiEvent(const char* format, ...) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000813 DCHECK(log_->IsEnabled() && FLAG_log_api);
814 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000815 va_list ap;
816 va_start(ap, format);
817 msg.AppendVA(format, ap);
818 va_end(ap);
819 msg.WriteToLogFile();
820}
Steve Blocka7e24c12009-10-30 11:49:00 +0000821
822
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000823void Logger::ApiSecurityCheck() {
Steve Block44f0eee2011-05-26 01:26:41 +0100824 if (!log_->IsEnabled() || !FLAG_log_api) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 ApiEvent("api,check-security");
Steve Blocka7e24c12009-10-30 11:49:00 +0000826}
827
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000828void Logger::SharedLibraryEvent(const std::string& library_path,
Ben Murdochc5610432016-08-08 18:44:38 +0100829 uintptr_t start, uintptr_t end,
830 intptr_t aslr_slide) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831 if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000832 Log::MessageBuilder msg(log_);
Ben Murdochc5610432016-08-08 18:44:38 +0100833 msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR
834 ",%" V8PRIdPTR,
835 library_path.c_str(), start, end, aslr_slide);
Steve Blocka7e24c12009-10-30 11:49:00 +0000836 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000837}
838
839
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000840void Logger::CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) {
841 PROFILER_LOG(CodeDeoptEvent(code, pc, fp_to_sp_delta));
842 if (!log_->IsEnabled() || !FLAG_log_internal_timer_events) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000843 Log::MessageBuilder msg(log_);
844 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
Ben Murdochc5610432016-08-08 18:44:38 +0100845 msg.Append("code-deopt,%d,%d", since_epoch, code->CodeSize());
Steve Blocka7e24c12009-10-30 11:49:00 +0000846 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000847}
848
849
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000850void Logger::CurrentTimeEvent() {
851 if (!log_->IsEnabled()) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852 DCHECK(FLAG_log_timer_events || FLAG_prof_cpp);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853 Log::MessageBuilder msg(log_);
854 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
Ben Murdochc5610432016-08-08 18:44:38 +0100855 msg.Append("current-time,%d", since_epoch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000856 msg.WriteToLogFile();
857}
858
859
860void Logger::TimerEvent(Logger::StartEnd se, const char* name) {
861 if (!log_->IsEnabled()) return;
862 DCHECK(FLAG_log_internal_timer_events);
863 Log::MessageBuilder msg(log_);
864 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
865 const char* format = (se == START) ? "timer-event-start,\"%s\",%ld"
866 : "timer-event-end,\"%s\",%ld";
867 msg.Append(format, name, since_epoch);
868 msg.WriteToLogFile();
869}
870
871
872void Logger::EnterExternal(Isolate* isolate) {
873 LOG(isolate, TimerEvent(START, TimerEventExternal::name()));
874 DCHECK(isolate->current_vm_state() == JS);
875 isolate->set_current_vm_state(EXTERNAL);
876}
877
878
879void Logger::LeaveExternal(Isolate* isolate) {
880 LOG(isolate, TimerEvent(END, TimerEventExternal::name()));
881 DCHECK(isolate->current_vm_state() == EXTERNAL);
882 isolate->set_current_vm_state(JS);
883}
884
885
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000886template <class TimerEvent>
887void TimerEventScope<TimerEvent>::LogTimerEvent(Logger::StartEnd se) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400888 Logger::CallEventLogger(isolate_, TimerEvent::name(), se,
889 TimerEvent::expose_to_api());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000890}
891
892
893// Instantiate template methods.
894#define V(TimerName, expose) \
895 template void TimerEventScope<TimerEvent##TimerName>::LogTimerEvent( \
896 Logger::StartEnd se);
897TIMER_EVENTS_LIST(V)
898#undef V
899
900
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000901namespace {
902// Emits the source code of a regexp. Used by regexp events.
903void LogRegExpSource(Handle<JSRegExp> regexp, Isolate* isolate,
904 Log::MessageBuilder* msg) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000905 // Prints "/" + re.source + "/" +
906 // (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
Steve Blocka7e24c12009-10-30 11:49:00 +0000907
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000908 Handle<Object> source =
Ben Murdochda12d292016-06-02 14:46:10 +0100909 JSReceiver::GetProperty(isolate, regexp, "source").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000910 if (!source->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000911 msg->Append("no source");
Steve Blocka7e24c12009-10-30 11:49:00 +0000912 return;
913 }
914
915 switch (regexp->TypeTag()) {
916 case JSRegExp::ATOM:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000917 msg->Append('a');
Steve Blocka7e24c12009-10-30 11:49:00 +0000918 break;
919 default:
920 break;
921 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000922 msg->Append('/');
923 msg->AppendDetailed(*Handle<String>::cast(source), false);
924 msg->Append('/');
Steve Blocka7e24c12009-10-30 11:49:00 +0000925
926 // global flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000927 Handle<Object> global =
Ben Murdochda12d292016-06-02 14:46:10 +0100928 JSReceiver::GetProperty(isolate, regexp, "global").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000929 if (global->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000930 msg->Append('g');
Steve Blocka7e24c12009-10-30 11:49:00 +0000931 }
932 // ignorecase flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000933 Handle<Object> ignorecase =
Ben Murdochda12d292016-06-02 14:46:10 +0100934 JSReceiver::GetProperty(isolate, regexp, "ignoreCase").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000935 if (ignorecase->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000936 msg->Append('i');
Steve Blocka7e24c12009-10-30 11:49:00 +0000937 }
938 // multiline flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000939 Handle<Object> multiline =
Ben Murdochda12d292016-06-02 14:46:10 +0100940 JSReceiver::GetProperty(isolate, regexp, "multiline").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000941 if (multiline->IsTrue()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000942 msg->Append('m');
Steve Blocka7e24c12009-10-30 11:49:00 +0000943 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000944}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000945} // namespace
Steve Blocka7e24c12009-10-30 11:49:00 +0000946
947
948void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
Steve Block44f0eee2011-05-26 01:26:41 +0100949 if (!log_->IsEnabled() || !FLAG_log_regexp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000951 msg.Append("regexp-compile,");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000952 LogRegExpSource(regexp, isolate_, &msg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000953 msg.Append(in_cache ? ",hit" : ",miss");
Steve Blocka7e24c12009-10-30 11:49:00 +0000954 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000955}
956
957
Steve Blocka7e24c12009-10-30 11:49:00 +0000958void Logger::ApiNamedPropertyAccess(const char* tag,
959 JSObject* holder,
960 Object* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000961 DCHECK(name->IsName());
Steve Block44f0eee2011-05-26 01:26:41 +0100962 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000963 String* class_name_obj = holder->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000964 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +0000965 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000966 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000967 base::SmartArrayPointer<char> property_name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
969 ApiEvent("api,%s,\"%s\",\"%s\"", tag, class_name.get(),
970 property_name.get());
971 } else {
972 Symbol* symbol = Symbol::cast(name);
973 uint32_t hash = symbol->Hash();
974 if (symbol->name()->IsUndefined()) {
975 ApiEvent("api,%s,\"%s\",symbol(hash %x)", tag, class_name.get(), hash);
976 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000977 base::SmartArrayPointer<char> str =
978 String::cast(symbol->name())
979 ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000980 ApiEvent("api,%s,\"%s\",symbol(\"%s\" hash %x)", tag, class_name.get(),
981 str.get(), hash);
982 }
983 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000984}
985
986void Logger::ApiIndexedPropertyAccess(const char* tag,
987 JSObject* holder,
988 uint32_t index) {
Steve Block44f0eee2011-05-26 01:26:41 +0100989 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000990 String* class_name_obj = holder->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000991 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +0000992 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000993 ApiEvent("api,%s,\"%s\",%u", tag, class_name.get(), index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000994}
995
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000996
Steve Blocka7e24c12009-10-30 11:49:00 +0000997void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
Steve Block44f0eee2011-05-26 01:26:41 +0100998 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000999 String* class_name_obj = object->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001000 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +00001001 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001002 ApiEvent("api,%s,\"%s\"", tag, class_name.get());
Steve Blocka7e24c12009-10-30 11:49:00 +00001003}
1004
1005
1006void Logger::ApiEntryCall(const char* name) {
Steve Block44f0eee2011-05-26 01:26:41 +01001007 if (!log_->IsEnabled() || !FLAG_log_api) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001008 ApiEvent("api,%s", name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001009}
1010
1011
1012void Logger::NewEvent(const char* name, void* object, size_t size) {
Steve Block44f0eee2011-05-26 01:26:41 +01001013 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014 Log::MessageBuilder msg(log_);
Ben Murdochc5610432016-08-08 18:44:38 +01001015 msg.Append("new,%s,%p,%u", name, object, static_cast<unsigned int>(size));
Steve Blocka7e24c12009-10-30 11:49:00 +00001016 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001017}
1018
1019
1020void Logger::DeleteEvent(const char* name, void* object) {
Steve Block44f0eee2011-05-26 01:26:41 +01001021 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001022 Log::MessageBuilder msg(log_);
Ben Murdochc5610432016-08-08 18:44:38 +01001023 msg.Append("delete,%s,%p", name, object);
Steve Blocka7e24c12009-10-30 11:49:00 +00001024 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001025}
1026
1027
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001028void Logger::CallbackEventInternal(const char* prefix, Name* name,
Steve Blockd0582a62009-12-15 09:54:21 +00001029 Address entry_point) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001030 if (!FLAG_log_code || !log_->IsEnabled()) return;
1031 Log::MessageBuilder msg(log_);
1032 msg.Append("%s,%s,-2,",
Ben Murdochb0fe1622011-05-05 13:52:32 +01001033 kLogEventsNames[CODE_CREATION_EVENT],
1034 kLogEventsNames[CALLBACK_TAG]);
Steve Blockd0582a62009-12-15 09:54:21 +00001035 msg.AppendAddress(entry_point);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001036 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001037 base::SmartArrayPointer<char> str =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001038 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1039 msg.Append(",1,\"%s%s\"", prefix, str.get());
1040 } else {
1041 Symbol* symbol = Symbol::cast(name);
1042 if (symbol->name()->IsUndefined()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001043 msg.Append(",1,symbol(hash %x)", symbol->Hash());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001044 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001045 base::SmartArrayPointer<char> str =
1046 String::cast(symbol->name())
1047 ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochc5610432016-08-08 18:44:38 +01001048 msg.Append(",1,symbol(\"%s%s\" hash %x)", prefix, str.get(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001049 symbol->Hash());
1050 }
1051 }
Steve Blockd0582a62009-12-15 09:54:21 +00001052 msg.WriteToLogFile();
1053}
Steve Blockd0582a62009-12-15 09:54:21 +00001054
1055
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056void Logger::CallbackEvent(Name* name, Address entry_point) {
1057 PROFILER_LOG(CallbackEvent(name, entry_point));
1058 CallbackEventInternal("", name, entry_point);
Steve Blockd0582a62009-12-15 09:54:21 +00001059}
1060
1061
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001062void Logger::GetterCallbackEvent(Name* name, Address entry_point) {
1063 PROFILER_LOG(GetterCallbackEvent(name, entry_point));
1064 CallbackEventInternal("get ", name, entry_point);
Steve Blockd0582a62009-12-15 09:54:21 +00001065}
1066
1067
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001068void Logger::SetterCallbackEvent(Name* name, Address entry_point) {
1069 PROFILER_LOG(SetterCallbackEvent(name, entry_point));
1070 CallbackEventInternal("set ", name, entry_point);
1071}
1072
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001073static void AppendCodeCreateHeader(Log::MessageBuilder* msg,
1074 Logger::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +01001075 AbstractCode* code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001076 DCHECK(msg);
1077 msg->Append("%s,%s,%d,",
1078 kLogEventsNames[Logger::CODE_CREATION_EVENT],
1079 kLogEventsNames[tag],
1080 code->kind());
1081 msg->AppendAddress(code->address());
1082 msg->Append(",%d,", code->ExecutableSize());
Steve Blockd0582a62009-12-15 09:54:21 +00001083}
1084
Ben Murdochda12d292016-06-02 14:46:10 +01001085void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
Steve Blocka7e24c12009-10-30 11:49:00 +00001086 const char* comment) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087 PROFILER_LOG(CodeCreateEvent(tag, code, comment));
1088
1089 if (!is_logging_code_events()) return;
1090 CALL_LISTENERS(CodeCreateEvent(tag, code, comment));
1091
1092 if (!FLAG_log_code || !log_->IsEnabled()) return;
1093 Log::MessageBuilder msg(log_);
1094 AppendCodeCreateHeader(&msg, tag, code);
1095 msg.AppendDoubleQuotedString(comment);
Steve Blocka7e24c12009-10-30 11:49:00 +00001096 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001097}
1098
Ben Murdochda12d292016-06-02 14:46:10 +01001099void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001100 Name* name) {
1101 PROFILER_LOG(CodeCreateEvent(tag, code, name));
1102
1103 if (!is_logging_code_events()) return;
1104 CALL_LISTENERS(CodeCreateEvent(tag, code, name));
1105
1106 if (!FLAG_log_code || !log_->IsEnabled()) return;
1107 Log::MessageBuilder msg(log_);
1108 AppendCodeCreateHeader(&msg, tag, code);
1109 if (name->IsString()) {
1110 msg.Append('"');
1111 msg.AppendDetailed(String::cast(name), false);
1112 msg.Append('"');
1113 } else {
1114 msg.AppendSymbolName(Symbol::cast(name));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001115 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001116 msg.WriteToLogFile();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001117}
1118
Ben Murdochda12d292016-06-02 14:46:10 +01001119void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
Ben Murdochc5610432016-08-08 18:44:38 +01001120 SharedFunctionInfo* shared, Name* name) {
1121 PROFILER_LOG(CodeCreateEvent(tag, code, shared, name));
Steve Block44f0eee2011-05-26 01:26:41 +01001122
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001123 if (!is_logging_code_events()) return;
Ben Murdochc5610432016-08-08 18:44:38 +01001124 CALL_LISTENERS(CodeCreateEvent(tag, code, shared, name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001125
1126 if (!FLAG_log_code || !log_->IsEnabled()) return;
Ben Murdochda12d292016-06-02 14:46:10 +01001127 if (code == AbstractCode::cast(
1128 isolate_->builtins()->builtin(Builtins::kCompileLazy))) {
1129 return;
1130 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001131
1132 Log::MessageBuilder msg(log_);
1133 AppendCodeCreateHeader(&msg, tag, code);
1134 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001135 base::SmartArrayPointer<char> str =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001136 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1137 msg.Append("\"%s\"", str.get());
1138 } else {
1139 msg.AppendSymbolName(Symbol::cast(name));
1140 }
1141 msg.Append(',');
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001142 msg.AppendAddress(shared->address());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001143 msg.Append(",%s", ComputeMarker(shared, code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001144 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001145}
1146
1147
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001148// Although, it is possible to extract source and line from
1149// the SharedFunctionInfo object, we left it to caller
1150// to leave logging functions free from heap allocations.
Ben Murdochda12d292016-06-02 14:46:10 +01001151void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
Ben Murdochc5610432016-08-08 18:44:38 +01001152 SharedFunctionInfo* shared, Name* source, int line,
1153 int column) {
1154 PROFILER_LOG(CodeCreateEvent(tag, code, shared, source, line, column));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001155
1156 if (!is_logging_code_events()) return;
Ben Murdochc5610432016-08-08 18:44:38 +01001157 CALL_LISTENERS(CodeCreateEvent(tag, code, shared, source, line, column));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001158
1159 if (!FLAG_log_code || !log_->IsEnabled()) return;
1160 Log::MessageBuilder msg(log_);
1161 AppendCodeCreateHeader(&msg, tag, code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001162 base::SmartArrayPointer<char> name =
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001163 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001164 msg.Append("\"%s ", name.get());
1165 if (source->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001166 base::SmartArrayPointer<char> sourcestr = String::cast(source)->ToCString(
1167 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168 msg.Append("%s", sourcestr.get());
1169 } else {
1170 msg.AppendSymbolName(Symbol::cast(source));
1171 }
1172 msg.Append(":%d:%d\",", line, column);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001173 msg.AppendAddress(shared->address());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001174 msg.Append(",%s", ComputeMarker(shared, code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001175 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001176}
1177
Ben Murdochda12d292016-06-02 14:46:10 +01001178void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001179 int args_count) {
1180 PROFILER_LOG(CodeCreateEvent(tag, code, args_count));
1181
1182 if (!is_logging_code_events()) return;
1183 CALL_LISTENERS(CodeCreateEvent(tag, code, args_count));
1184
1185 if (!FLAG_log_code || !log_->IsEnabled()) return;
1186 Log::MessageBuilder msg(log_);
1187 AppendCodeCreateHeader(&msg, tag, code);
1188 msg.Append("\"args_count: %d\"", args_count);
1189 msg.WriteToLogFile();
1190}
1191
Ben Murdochda12d292016-06-02 14:46:10 +01001192void Logger::CodeDisableOptEvent(AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001193 SharedFunctionInfo* shared) {
1194 PROFILER_LOG(CodeDisableOptEvent(code, shared));
1195
1196 if (!is_logging_code_events()) return;
1197 CALL_LISTENERS(CodeDisableOptEvent(code, shared));
1198
1199 if (!FLAG_log_code || !log_->IsEnabled()) return;
1200 Log::MessageBuilder msg(log_);
1201 msg.Append("%s,", kLogEventsNames[CODE_DISABLE_OPT_EVENT]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001202 base::SmartArrayPointer<char> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001203 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1204 msg.Append("\"%s\",", name.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001205 msg.Append("\"%s\"", GetBailoutReason(shared->disable_optimization_reason()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001206 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001207}
1208
1209
Ben Murdochf87a2032010-10-22 12:50:53 +01001210void Logger::CodeMovingGCEvent() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001211 PROFILER_LOG(CodeMovingGCEvent());
1212
1213 if (!is_logging_code_events()) return;
Ben Murdoch257744e2011-11-30 15:57:28 +00001214 if (!log_->IsEnabled() || !FLAG_ll_prof) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001215 CALL_LISTENERS(CodeMovingGCEvent());
1216 base::OS::SignalCodeMovingGC();
Ben Murdochf87a2032010-10-22 12:50:53 +01001217}
1218
Ben Murdochda12d292016-06-02 14:46:10 +01001219void Logger::RegExpCodeCreateEvent(AbstractCode* code, String* source) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001220 PROFILER_LOG(RegExpCodeCreateEvent(code, source));
1221
1222 if (!is_logging_code_events()) return;
1223 CALL_LISTENERS(RegExpCodeCreateEvent(code, source));
1224
1225 if (!FLAG_log_code || !log_->IsEnabled()) return;
1226 Log::MessageBuilder msg(log_);
1227 AppendCodeCreateHeader(&msg, REG_EXP_TAG, code);
1228 msg.Append('"');
Steve Blocka7e24c12009-10-30 11:49:00 +00001229 msg.AppendDetailed(source, false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001230 msg.Append('"');
Steve Blocka7e24c12009-10-30 11:49:00 +00001231 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001232}
1233
Ben Murdochda12d292016-06-02 14:46:10 +01001234void Logger::CodeMoveEvent(AbstractCode* from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001235 PROFILER_LOG(CodeMoveEvent(from, to));
1236
1237 if (!is_logging_code_events()) return;
1238 CALL_LISTENERS(CodeMoveEvent(from, to));
Ben Murdochda12d292016-06-02 14:46:10 +01001239 MoveEventInternal(CODE_MOVE_EVENT, from->address(), to);
Steve Blocka7e24c12009-10-30 11:49:00 +00001240}
1241
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001242void Logger::CodeLinePosInfoAddPositionEvent(void* jit_handler_data,
Ben Murdochda12d292016-06-02 14:46:10 +01001243 int pc_offset, int position) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001244 JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1245 pc_offset,
1246 position,
1247 JitCodeEvent::POSITION));
1248}
1249
1250
1251void Logger::CodeLinePosInfoAddStatementPositionEvent(void* jit_handler_data,
1252 int pc_offset,
1253 int position) {
1254 JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1255 pc_offset,
1256 position,
1257 JitCodeEvent::STATEMENT_POSITION));
1258}
1259
1260
1261void Logger::CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder) {
1262 if (jit_logger_ != NULL) {
1263 pos_recorder->AttachJITHandlerData(jit_logger_->StartCodePosInfoEvent());
Ben Murdoch257744e2011-11-30 15:57:28 +00001264 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001265}
1266
Ben Murdochda12d292016-06-02 14:46:10 +01001267void Logger::CodeEndLinePosInfoRecordEvent(AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001268 void* jit_handler_data) {
1269 JIT_LOG(EndCodePosInfoEvent(code, jit_handler_data));
1270}
1271
1272
1273void Logger::CodeNameEvent(Address addr, int pos, const char* code_name) {
1274 if (code_name == NULL) return; // Not a code object.
1275 Log::MessageBuilder msg(log_);
1276 msg.Append("%s,%d,", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
1277 msg.AppendDoubleQuotedString(code_name);
1278 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001279}
1280
1281
Steve Block44f0eee2011-05-26 01:26:41 +01001282void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001283 if (!is_logging_code_events()) return;
Steve Block44f0eee2011-05-26 01:26:41 +01001284 MoveEventInternal(SHARED_FUNC_MOVE_EVENT, from, to);
Leon Clarked91b9f72010-01-27 17:25:45 +00001285}
1286
1287
Leon Clarked91b9f72010-01-27 17:25:45 +00001288void Logger::MoveEventInternal(LogEventsAndTags event,
1289 Address from,
1290 Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 if (!FLAG_log_code || !log_->IsEnabled()) return;
1292 Log::MessageBuilder msg(log_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001293 msg.Append("%s,", kLogEventsNames[event]);
Leon Clarked91b9f72010-01-27 17:25:45 +00001294 msg.AppendAddress(from);
1295 msg.Append(',');
Ben Murdochb0fe1622011-05-05 13:52:32 +01001296 msg.AppendAddress(to);
Leon Clarked91b9f72010-01-27 17:25:45 +00001297 msg.WriteToLogFile();
1298}
Leon Clarked91b9f72010-01-27 17:25:45 +00001299
1300
Steve Blocka7e24c12009-10-30 11:49:00 +00001301void Logger::ResourceEvent(const char* name, const char* tag) {
Steve Block44f0eee2011-05-26 01:26:41 +01001302 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001303 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001304 msg.Append("%s,%s,", name, tag);
1305
1306 uint32_t sec, usec;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001307 if (base::OS::GetUserTime(&sec, &usec) != -1) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001308 msg.Append("%d,%d,", sec, usec);
1309 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001310 msg.Append("%.0f", base::OS::TimeCurrentMillis());
Steve Blocka7e24c12009-10-30 11:49:00 +00001311 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001312}
1313
1314
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001315void Logger::SuspectReadEvent(Name* name, Object* obj) {
Steve Block44f0eee2011-05-26 01:26:41 +01001316 if (!log_->IsEnabled() || !FLAG_log_suspect) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001317 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001318 String* class_name = obj->IsJSObject()
1319 ? JSObject::cast(obj)->class_name()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001320 : isolate_->heap()->empty_string();
Steve Blocka7e24c12009-10-30 11:49:00 +00001321 msg.Append("suspect-read,");
1322 msg.Append(class_name);
1323 msg.Append(',');
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001324 if (name->IsString()) {
1325 msg.Append('"');
1326 msg.Append(String::cast(name));
1327 msg.Append('"');
1328 } else {
1329 msg.AppendSymbolName(Symbol::cast(name));
1330 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001331 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001332}
1333
1334
1335void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
Steve Block44f0eee2011-05-26 01:26:41 +01001336 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001337 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001338 // Using non-relative system time in order to be able to synchronize with
1339 // external memory profiling events (e.g. DOM memory size).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001340 msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f", space, kind,
1341 base::OS::TimeCurrentMillis());
Steve Blocka7e24c12009-10-30 11:49:00 +00001342 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001343}
1344
1345
1346void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
Steve Block44f0eee2011-05-26 01:26:41 +01001347 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001348 Log::MessageBuilder msg(log_);
1349 msg.Append("heap-sample-end,\"%s\",\"%s\"", space, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001350 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001351}
1352
1353
1354void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
Steve Block44f0eee2011-05-26 01:26:41 +01001355 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356 Log::MessageBuilder msg(log_);
1357 msg.Append("heap-sample-item,%s,%d,%d", type, number, bytes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001358 msg.WriteToLogFile();
Steve Block3ce2e202009-11-05 08:53:23 +00001359}
1360
1361
Steve Blocka7e24c12009-10-30 11:49:00 +00001362void Logger::DebugTag(const char* call_site_tag) {
Steve Block44f0eee2011-05-26 01:26:41 +01001363 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001364 Log::MessageBuilder msg(log_);
1365 msg.Append("debug-tag,%s", call_site_tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001366 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001367}
1368
1369
1370void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
Steve Block44f0eee2011-05-26 01:26:41 +01001371 if (!log_->IsEnabled() || !FLAG_log) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001372 StringBuilder s(parameter.length() + 1);
1373 for (int i = 0; i < parameter.length(); ++i) {
1374 s.AddCharacter(static_cast<char>(parameter[i]));
1375 }
1376 char* parameter_string = s.Finalize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001377 Log::MessageBuilder msg(log_);
1378 msg.Append("debug-queue-event,%s,%15.3f,%s", event_type,
1379 base::OS::TimeCurrentMillis(), parameter_string);
Steve Blocka7e24c12009-10-30 11:49:00 +00001380 DeleteArray(parameter_string);
1381 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001382}
1383
1384
Steve Blocka7e24c12009-10-30 11:49:00 +00001385void Logger::TickEvent(TickSample* sample, bool overflow) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001386 if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387 Log::MessageBuilder msg(log_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001388 msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
1389 msg.AppendAddress(sample->pc);
Ben Murdochc5610432016-08-08 18:44:38 +01001390 msg.Append(",%d", static_cast<int>(timer_.Elapsed().InMicroseconds()));
Steve Block44f0eee2011-05-26 01:26:41 +01001391 if (sample->has_external_callback) {
1392 msg.Append(",1,");
Ben Murdoch097c5b22016-05-18 11:27:45 +01001393 msg.AppendAddress(sample->external_callback_entry);
Steve Block44f0eee2011-05-26 01:26:41 +01001394 } else {
1395 msg.Append(",0,");
1396 msg.AppendAddress(sample->tos);
1397 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001398 msg.Append(",%d", static_cast<int>(sample->state));
1399 if (overflow) {
1400 msg.Append(",overflow");
1401 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001402 for (unsigned i = 0; i < sample->frames_count; ++i) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001403 msg.Append(',');
Ben Murdochb0fe1622011-05-05 13:52:32 +01001404 msg.AppendAddress(sample->stack[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001405 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001406 msg.WriteToLogFile();
1407}
1408
1409
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001410void Logger::StopProfiler() {
Steve Block44f0eee2011-05-26 01:26:41 +01001411 if (!log_->IsEnabled()) return;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001412 if (profiler_ != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001413 profiler_->pause();
1414 is_logging_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001415 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001416}
1417
1418
1419// This function can be called when Log's mutex is acquired,
1420// either from main or Profiler's thread.
Steve Block44f0eee2011-05-26 01:26:41 +01001421void Logger::LogFailure() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001422 StopProfiler();
Steve Blocka7e24c12009-10-30 11:49:00 +00001423}
1424
1425
Ben Murdochb0fe1622011-05-05 13:52:32 +01001426class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor {
1427 public:
1428 EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis,
Ben Murdochda12d292016-06-02 14:46:10 +01001429 Handle<AbstractCode>* code_objects,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001430 int* count)
Ben Murdochda12d292016-06-02 14:46:10 +01001431 : sfis_(sfis), code_objects_(code_objects), count_(count) {}
Ben Murdochb0fe1622011-05-05 13:52:32 +01001432
1433 virtual void EnterContext(Context* context) {}
1434 virtual void LeaveContext(Context* context) {}
1435
1436 virtual void VisitFunction(JSFunction* function) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001437 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(function->shared());
1438 Object* maybe_script = sfi->script();
1439 if (maybe_script->IsScript()
1440 && !Script::cast(maybe_script)->HasValidSource()) return;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001441 if (sfis_ != NULL) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001442 sfis_[*count_] = Handle<SharedFunctionInfo>(sfi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001443 }
1444 if (code_objects_ != NULL) {
Ben Murdochda12d292016-06-02 14:46:10 +01001445 DCHECK(function->abstract_code()->kind() ==
1446 AbstractCode::OPTIMIZED_FUNCTION);
1447 code_objects_[*count_] = Handle<AbstractCode>(function->abstract_code());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001448 }
1449 *count_ = *count_ + 1;
1450 }
1451
1452 private:
1453 Handle<SharedFunctionInfo>* sfis_;
Ben Murdochda12d292016-06-02 14:46:10 +01001454 Handle<AbstractCode>* code_objects_;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001455 int* count_;
1456};
1457
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001458static int EnumerateCompiledFunctions(Heap* heap,
1459 Handle<SharedFunctionInfo>* sfis,
Ben Murdochda12d292016-06-02 14:46:10 +01001460 Handle<AbstractCode>* code_objects) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001461 HeapIterator iterator(heap);
1462 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001463 int compiled_funcs_count = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001464
1465 // Iterate the heap to find shared function info objects and record
1466 // the unoptimized code for them.
Leon Clarked91b9f72010-01-27 17:25:45 +00001467 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001468 if (!obj->IsSharedFunctionInfo()) continue;
1469 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
1470 if (sfi->is_compiled()
1471 && (!sfi->script()->IsScript()
1472 || Script::cast(sfi->script())->HasValidSource())) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001473 if (sfis != NULL) {
Steve Block3ce2e202009-11-05 08:53:23 +00001474 sfis[compiled_funcs_count] = Handle<SharedFunctionInfo>(sfi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001475 }
1476 if (code_objects != NULL) {
Ben Murdochda12d292016-06-02 14:46:10 +01001477 code_objects[compiled_funcs_count] =
1478 Handle<AbstractCode>(sfi->abstract_code());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001479 }
Steve Block3ce2e202009-11-05 08:53:23 +00001480 ++compiled_funcs_count;
Steve Blocka7e24c12009-10-30 11:49:00 +00001481 }
1482 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001483
1484 // Iterate all optimized functions in all contexts.
1485 EnumerateOptimizedFunctionsVisitor visitor(sfis,
1486 code_objects,
1487 &compiled_funcs_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001488 Deoptimizer::VisitAllOptimizedFunctions(heap->isolate(), &visitor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001489
Steve Block3ce2e202009-11-05 08:53:23 +00001490 return compiled_funcs_count;
1491}
1492
1493
Steve Blockd0582a62009-12-15 09:54:21 +00001494void Logger::LogCodeObject(Object* object) {
Ben Murdochda12d292016-06-02 14:46:10 +01001495 AbstractCode* code_object = AbstractCode::cast(object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001496 LogEventsAndTags tag = Logger::STUB_TAG;
1497 const char* description = "Unknown code from the snapshot";
1498 switch (code_object->kind()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001499 case AbstractCode::FUNCTION:
1500 case AbstractCode::INTERPRETED_FUNCTION:
1501 case AbstractCode::OPTIMIZED_FUNCTION:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001502 return; // We log this later using LogCompiledFunctions.
Ben Murdochda12d292016-06-02 14:46:10 +01001503 case AbstractCode::BYTECODE_HANDLER:
1504 return; // We log it later by walking the dispatch table.
1505 case AbstractCode::BINARY_OP_IC: // fall through
1506 case AbstractCode::COMPARE_IC: // fall through
1507 case AbstractCode::TO_BOOLEAN_IC: // fall through
1508
1509 case AbstractCode::STUB:
1510 description =
1511 CodeStub::MajorName(CodeStub::GetMajorKey(code_object->GetCode()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001512 if (description == NULL)
1513 description = "A stub from the snapshot";
1514 tag = Logger::STUB_TAG;
1515 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001516 case AbstractCode::REGEXP:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001517 description = "Regular expression code";
1518 tag = Logger::REG_EXP_TAG;
1519 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001520 case AbstractCode::BUILTIN:
1521 description =
1522 isolate_->builtins()->name(code_object->GetCode()->builtin_index());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001523 tag = Logger::BUILTIN_TAG;
1524 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001525 case AbstractCode::HANDLER:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001526 description = "An IC handler from the snapshot";
1527 tag = Logger::HANDLER_TAG;
1528 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001529 case AbstractCode::KEYED_LOAD_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001530 description = "A keyed load IC from the snapshot";
1531 tag = Logger::KEYED_LOAD_IC_TAG;
1532 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001533 case AbstractCode::LOAD_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001534 description = "A load IC from the snapshot";
1535 tag = Logger::LOAD_IC_TAG;
1536 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001537 case AbstractCode::CALL_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001538 description = "A call IC from the snapshot";
1539 tag = Logger::CALL_IC_TAG;
1540 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001541 case AbstractCode::STORE_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001542 description = "A store IC from the snapshot";
1543 tag = Logger::STORE_IC_TAG;
1544 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001545 case AbstractCode::KEYED_STORE_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001546 description = "A keyed store IC from the snapshot";
1547 tag = Logger::KEYED_STORE_IC_TAG;
1548 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001549 case AbstractCode::WASM_FUNCTION:
1550 description = "A Wasm function";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001551 tag = Logger::STUB_TAG;
1552 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001553 case AbstractCode::JS_TO_WASM_FUNCTION:
1554 description = "A JavaScript to Wasm adapter";
1555 tag = Logger::STUB_TAG;
1556 break;
1557 case AbstractCode::WASM_TO_JS_FUNCTION:
1558 description = "A Wasm to JavaScript adapter";
1559 tag = Logger::STUB_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001560 break;
Steve Blockd0582a62009-12-15 09:54:21 +00001561 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001562 PROFILE(isolate_, CodeCreateEvent(tag, code_object, description));
Ben Murdochf87a2032010-10-22 12:50:53 +01001563}
1564
1565
Andrei Popescu31002712010-02-23 13:46:05 +00001566void Logger::LogCodeObjects() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001567 Heap* heap = isolate_->heap();
1568 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001569 "Logger::LogCodeObjects");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001570 HeapIterator iterator(heap);
1571 DisallowHeapAllocation no_gc;
Andrei Popescu31002712010-02-23 13:46:05 +00001572 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1573 if (obj->IsCode()) LogCodeObject(obj);
Ben Murdochda12d292016-06-02 14:46:10 +01001574 if (obj->IsBytecodeArray()) LogCodeObject(obj);
Andrei Popescu31002712010-02-23 13:46:05 +00001575 }
1576}
1577
Ben Murdochda12d292016-06-02 14:46:10 +01001578void Logger::LogBytecodeHandlers() {
1579 if (!FLAG_ignition) return;
1580
Ben Murdochc5610432016-08-08 18:44:38 +01001581 const interpreter::OperandScale kOperandScales[] = {
1582#define VALUE(Name, _) interpreter::OperandScale::k##Name,
1583 OPERAND_SCALE_LIST(VALUE)
1584#undef VALUE
1585 };
1586
Ben Murdochda12d292016-06-02 14:46:10 +01001587 const int last_index = static_cast<int>(interpreter::Bytecode::kLast);
Ben Murdochc5610432016-08-08 18:44:38 +01001588 interpreter::Interpreter* interpreter = isolate_->interpreter();
1589 for (auto operand_scale : kOperandScales) {
Ben Murdochda12d292016-06-02 14:46:10 +01001590 for (int index = 0; index <= last_index; ++index) {
1591 interpreter::Bytecode bytecode = interpreter::Bytecodes::FromByte(index);
1592 if (interpreter::Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) {
1593 Code* code = interpreter->GetBytecodeHandler(bytecode, operand_scale);
1594 std::string bytecode_name =
1595 interpreter::Bytecodes::ToString(bytecode, operand_scale);
1596 CodeCreateEvent(Logger::BYTECODE_HANDLER_TAG, AbstractCode::cast(code),
1597 bytecode_name.c_str());
1598 }
1599 }
1600 }
1601}
Andrei Popescu31002712010-02-23 13:46:05 +00001602
Ben Murdoch589d6972011-11-30 16:04:58 +00001603void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
Ben Murdochda12d292016-06-02 14:46:10 +01001604 Handle<AbstractCode> code) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001605 Handle<String> func_name(shared->DebugName());
1606 if (shared->script()->IsScript()) {
1607 Handle<Script> script(Script::cast(shared->script()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001608 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
1609 int column_num =
1610 Script::GetColumnNumber(script, shared->start_position()) + 1;
Ben Murdoch589d6972011-11-30 16:04:58 +00001611 if (script->name()->IsString()) {
1612 Handle<String> script_name(String::cast(script->name()));
Ben Murdoch589d6972011-11-30 16:04:58 +00001613 if (line_num > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001614 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001615 CodeCreateEvent(
1616 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
Ben Murdochc5610432016-08-08 18:44:38 +01001617 *code, *shared, *script_name, line_num, column_num));
Ben Murdoch589d6972011-11-30 16:04:58 +00001618 } else {
1619 // Can't distinguish eval and script here, so always use Script.
Ben Murdochc5610432016-08-08 18:44:38 +01001620 PROFILE(isolate_, CodeCreateEvent(Logger::ToNativeByScript(
1621 Logger::SCRIPT_TAG, *script),
1622 *code, *shared, *script_name));
Ben Murdoch589d6972011-11-30 16:04:58 +00001623 }
1624 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001625 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001626 CodeCreateEvent(
1627 Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
Ben Murdochc5610432016-08-08 18:44:38 +01001628 *code, *shared, isolate_->heap()->empty_string(), line_num,
1629 column_num));
Ben Murdoch589d6972011-11-30 16:04:58 +00001630 }
1631 } else if (shared->IsApiFunction()) {
1632 // API function.
1633 FunctionTemplateInfo* fun_data = shared->get_api_func_data();
1634 Object* raw_call_data = fun_data->call_code();
1635 if (!raw_call_data->IsUndefined()) {
1636 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1637 Object* callback_obj = call_data->callback();
1638 Address entry_point = v8::ToCData<Address>(callback_obj);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001639#if USES_FUNCTION_DESCRIPTORS
1640 entry_point = *FUNCTION_ENTRYPOINT_ADDRESS(entry_point);
1641#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001642 PROFILE(isolate_, CallbackEvent(*func_name, entry_point));
Ben Murdoch589d6972011-11-30 16:04:58 +00001643 }
1644 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01001645 PROFILE(isolate_, CodeCreateEvent(Logger::LAZY_COMPILE_TAG, *code, *shared,
1646 *func_name));
Ben Murdoch589d6972011-11-30 16:04:58 +00001647 }
1648}
1649
1650
Steve Block3ce2e202009-11-05 08:53:23 +00001651void Logger::LogCompiledFunctions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001652 Heap* heap = isolate_->heap();
1653 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001654 "Logger::LogCompiledFunctions");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001655 HandleScope scope(isolate_);
1656 const int compiled_funcs_count = EnumerateCompiledFunctions(heap, NULL, NULL);
Kristian Monsen25f61362010-05-21 11:50:48 +01001657 ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
Ben Murdochda12d292016-06-02 14:46:10 +01001658 ScopedVector<Handle<AbstractCode> > code_objects(compiled_funcs_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001659 EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00001660
1661 // During iteration, there can be heap allocation due to
1662 // GetScriptLineNumber call.
1663 for (int i = 0; i < compiled_funcs_count; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001664 if (code_objects[i].is_identical_to(isolate_->builtins()->CompileLazy()))
Steve Block44f0eee2011-05-26 01:26:41 +01001665 continue;
Ben Murdoch589d6972011-11-30 16:04:58 +00001666 LogExistingFunction(sfis[i], code_objects[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001667 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001668}
1669
Steve Blockd0582a62009-12-15 09:54:21 +00001670
1671void Logger::LogAccessorCallbacks() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001672 Heap* heap = isolate_->heap();
1673 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001674 "Logger::LogAccessorCallbacks");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001675 HeapIterator iterator(heap);
1676 DisallowHeapAllocation no_gc;
Leon Clarked91b9f72010-01-27 17:25:45 +00001677 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001678 if (!obj->IsAccessorInfo()) continue;
1679 AccessorInfo* ai = AccessorInfo::cast(obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001680 if (!ai->name()->IsName()) continue;
Steve Blockd0582a62009-12-15 09:54:21 +00001681 Address getter_entry = v8::ToCData<Address>(ai->getter());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001682 Name* name = Name::cast(ai->name());
Steve Blockd0582a62009-12-15 09:54:21 +00001683 if (getter_entry != 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001684#if USES_FUNCTION_DESCRIPTORS
1685 getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(getter_entry);
1686#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001687 PROFILE(isolate_, GetterCallbackEvent(name, getter_entry));
Steve Blockd0582a62009-12-15 09:54:21 +00001688 }
1689 Address setter_entry = v8::ToCData<Address>(ai->setter());
1690 if (setter_entry != 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001691#if USES_FUNCTION_DESCRIPTORS
1692 setter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(setter_entry);
1693#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001694 PROFILE(isolate_, SetterCallbackEvent(name, setter_entry));
Steve Blockd0582a62009-12-15 09:54:21 +00001695 }
1696 }
1697}
1698
Steve Blocka7e24c12009-10-30 11:49:00 +00001699
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001700static void AddIsolateIdIfNeeded(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001701 Isolate* isolate) {
1702 if (FLAG_logfile_per_isolate) os << "isolate-" << isolate << "-";
1703}
1704
1705
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001706static void PrepareLogFileName(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001707 Isolate* isolate, const char* file_name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001708 int dir_separator_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001709 for (const char* p = file_name; *p; p++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001710 if (base::OS::isDirectorySeparator(*p)) dir_separator_count++;
1711 }
1712
1713 for (const char* p = file_name; *p; p++) {
1714 if (dir_separator_count == 0) {
1715 AddIsolateIdIfNeeded(os, isolate);
1716 dir_separator_count--;
1717 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001718 if (*p == '%') {
1719 p++;
1720 switch (*p) {
1721 case '\0':
1722 // If there's a % at the end of the string we back up
1723 // one character so we can escape the loop properly.
1724 p--;
1725 break;
1726 case 'p':
1727 os << base::OS::GetCurrentProcessId();
1728 break;
1729 case 't':
1730 // %t expands to the current time in milliseconds.
1731 os << static_cast<int64_t>(base::OS::TimeCurrentMillis());
1732 break;
1733 case '%':
1734 // %% expands (contracts really) to %.
1735 os << '%';
1736 break;
1737 default:
1738 // All other %'s expand to themselves.
1739 os << '%' << *p;
1740 break;
1741 }
1742 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001743 if (base::OS::isDirectorySeparator(*p)) dir_separator_count--;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001744 os << *p;
1745 }
1746 }
1747}
1748
1749
1750bool Logger::SetUp(Isolate* isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +01001751 // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
1752 if (is_initialized_) return true;
1753 is_initialized_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001754
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001755 std::ostringstream log_file_name;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001756 PrepareLogFileName(log_file_name, isolate, FLAG_logfile);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001757 log_->Initialize(log_file_name.str().c_str());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001758
1759
1760 if (FLAG_perf_basic_prof) {
1761 perf_basic_logger_ = new PerfBasicLogger();
1762 addCodeEventListener(perf_basic_logger_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001763 }
1764
Ben Murdochda12d292016-06-02 14:46:10 +01001765 if (FLAG_perf_prof) {
1766 perf_jit_logger_ = new PerfJitLogger();
1767 addCodeEventListener(perf_jit_logger_);
1768 }
1769
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001770 if (FLAG_ll_prof) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001771 ll_logger_ = new LowLevelLogger(log_file_name.str().c_str());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001772 addCodeEventListener(ll_logger_);
1773 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001774
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001775 ticker_ = new Ticker(isolate, kSamplingIntervalMs);
1776
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001777 if (Log::InitLogAtStart()) {
1778 is_logging_ = true;
Steve Block6ded16b2010-05-10 14:33:55 +01001779 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001780
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001781 if (FLAG_log_internal_timer_events || FLAG_prof_cpp) timer_.Start();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001782
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001783 if (FLAG_prof_cpp) {
Steve Block44f0eee2011-05-26 01:26:41 +01001784 profiler_ = new Profiler(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001785 is_logging_ = true;
1786 profiler_->Engage();
Steve Blocka7e24c12009-10-30 11:49:00 +00001787 }
1788
Steve Blocka7e24c12009-10-30 11:49:00 +00001789 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001790}
1791
1792
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001793void Logger::SetCodeEventHandler(uint32_t options,
1794 JitCodeEventHandler event_handler) {
1795 if (jit_logger_) {
1796 removeCodeEventListener(jit_logger_);
1797 delete jit_logger_;
1798 jit_logger_ = NULL;
1799 }
1800
1801 if (event_handler) {
1802 jit_logger_ = new JitLogger(event_handler);
1803 addCodeEventListener(jit_logger_);
1804 if (options & kJitCodeEventEnumExisting) {
1805 HandleScope scope(isolate_);
1806 LogCodeObjects();
1807 LogCompiledFunctions();
1808 }
1809 }
1810}
1811
1812
Steve Block44f0eee2011-05-26 01:26:41 +01001813Sampler* Logger::sampler() {
1814 return ticker_;
1815}
1816
1817
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001818FILE* Logger::TearDown() {
1819 if (!is_initialized_) return NULL;
Steve Block44f0eee2011-05-26 01:26:41 +01001820 is_initialized_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001821
1822 // Stop the profiler before closing the file.
1823 if (profiler_ != NULL) {
1824 profiler_->Disengage();
1825 delete profiler_;
1826 profiler_ = NULL;
1827 }
1828
Steve Blocka7e24c12009-10-30 11:49:00 +00001829 delete ticker_;
1830 ticker_ = NULL;
1831
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001832 if (perf_basic_logger_) {
1833 removeCodeEventListener(perf_basic_logger_);
1834 delete perf_basic_logger_;
1835 perf_basic_logger_ = NULL;
1836 }
1837
Ben Murdochda12d292016-06-02 14:46:10 +01001838 if (perf_jit_logger_) {
1839 removeCodeEventListener(perf_jit_logger_);
1840 delete perf_jit_logger_;
1841 perf_jit_logger_ = NULL;
1842 }
1843
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001844 if (ll_logger_) {
1845 removeCodeEventListener(ll_logger_);
1846 delete ll_logger_;
1847 ll_logger_ = NULL;
1848 }
1849
1850 if (jit_logger_) {
1851 removeCodeEventListener(jit_logger_);
1852 delete jit_logger_;
1853 jit_logger_ = NULL;
1854 }
1855
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001856 return log_->Close();
Steve Blocka7e24c12009-10-30 11:49:00 +00001857}
1858
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001859} // namespace internal
1860} // namespace v8