blob: 43c3981bcabaa61309b71accc2c80d3880fe05a9 [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 Murdoch61f157c2016-09-16 13:49:30 +010014#include "src/counters.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "src/deoptimizer.h"
16#include "src/global-handles.h"
Ben Murdochda12d292016-06-02 14:46:10 +010017#include "src/interpreter/bytecodes.h"
18#include "src/interpreter/interpreter.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010019#include "src/libsampler/v8-sampler.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020#include "src/log-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021#include "src/log-utils.h"
22#include "src/macro-assembler.h"
Ben Murdochda12d292016-06-02 14:46:10 +010023#include "src/perf-jit.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010024#include "src/profiler/cpu-profiler-inl.h"
25#include "src/profiler/profiler-listener.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000026#include "src/runtime-profiler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027#include "src/string-stream.h"
28#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000029
30namespace v8 {
31namespace internal {
32
Steve Blocka7e24c12009-10-30 11:49:00 +000033
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034#define DECLARE_EVENT(ignore1, name) name,
Ben Murdoch61f157c2016-09-16 13:49:30 +010035static const char* kLogEventsNames[CodeEventListener::NUMBER_OF_LOG_EVENTS] = {
36 LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037#undef DECLARE_EVENT
Steve Blocka7e24c12009-10-30 11:49:00 +000038
Ben Murdochda12d292016-06-02 14:46:10 +010039static const char* ComputeMarker(SharedFunctionInfo* shared,
40 AbstractCode* code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041 switch (code->kind()) {
Ben Murdochda12d292016-06-02 14:46:10 +010042 case AbstractCode::FUNCTION:
43 case AbstractCode::INTERPRETED_FUNCTION:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 return shared->optimization_disabled() ? "" : "~";
Ben Murdochda12d292016-06-02 14:46:10 +010045 case AbstractCode::OPTIMIZED_FUNCTION:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046 return "*";
47 default:
48 return "";
Steve Blocka7e24c12009-10-30 11:49:00 +000049 }
50}
51
52
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053class CodeEventLogger::NameBuffer {
Ben Murdoch257744e2011-11-30 15:57:28 +000054 public:
55 NameBuffer() { Reset(); }
56
57 void Reset() {
58 utf8_pos_ = 0;
59 }
60
Ben Murdoch61f157c2016-09-16 13:49:30 +010061 void Init(CodeEventListener::LogEventsAndTags tag) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 Reset();
63 AppendBytes(kLogEventsNames[tag]);
64 AppendByte(':');
65 }
66
67 void AppendName(Name* name) {
68 if (name->IsString()) {
69 AppendString(String::cast(name));
70 } else {
71 Symbol* symbol = Symbol::cast(name);
72 AppendBytes("symbol(");
Ben Murdoch61f157c2016-09-16 13:49:30 +010073 if (!symbol->name()->IsUndefined(symbol->GetIsolate())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074 AppendBytes("\"");
75 AppendString(String::cast(symbol->name()));
76 AppendBytes("\" ");
77 }
78 AppendBytes("hash ");
79 AppendHex(symbol->Hash());
80 AppendByte(')');
81 }
82 }
83
Ben Murdoch257744e2011-11-30 15:57:28 +000084 void AppendString(String* str) {
85 if (str == NULL) return;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010086 int uc16_length = Min(str->length(), kUtf16BufferSize);
87 String::WriteToFlat(str, utf16_buffer, 0, uc16_length);
88 int previous = unibrow::Utf16::kNoPreviousCharacter;
Ben Murdoch257744e2011-11-30 15:57:28 +000089 for (int i = 0; i < uc16_length && utf8_pos_ < kUtf8BufferSize; ++i) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010090 uc16 c = utf16_buffer[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091 if (c <= unibrow::Utf8::kMaxOneByteChar) {
Ben Murdoch257744e2011-11-30 15:57:28 +000092 utf8_buffer_[utf8_pos_++] = static_cast<char>(c);
93 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010094 int char_length = unibrow::Utf8::Length(c, previous);
Ben Murdoch257744e2011-11-30 15:57:28 +000095 if (utf8_pos_ + char_length > kUtf8BufferSize) break;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010096 unibrow::Utf8::Encode(utf8_buffer_ + utf8_pos_, c, previous);
Ben Murdoch257744e2011-11-30 15:57:28 +000097 utf8_pos_ += char_length;
98 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010099 previous = c;
Ben Murdoch257744e2011-11-30 15:57:28 +0000100 }
101 }
102
103 void AppendBytes(const char* bytes, int size) {
104 size = Min(size, kUtf8BufferSize - utf8_pos_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 MemCopy(utf8_buffer_ + utf8_pos_, bytes, size);
Ben Murdoch257744e2011-11-30 15:57:28 +0000106 utf8_pos_ += size;
107 }
108
109 void AppendBytes(const char* bytes) {
110 AppendBytes(bytes, StrLength(bytes));
111 }
112
113 void AppendByte(char c) {
114 if (utf8_pos_ >= kUtf8BufferSize) return;
115 utf8_buffer_[utf8_pos_++] = c;
116 }
117
118 void AppendInt(int n) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000119 int space = kUtf8BufferSize - utf8_pos_;
120 if (space <= 0) return;
121 Vector<char> buffer(utf8_buffer_ + utf8_pos_, space);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122 int size = SNPrintF(buffer, "%d", n);
123 if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
124 utf8_pos_ += size;
125 }
126 }
127
128 void AppendHex(uint32_t n) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 int space = kUtf8BufferSize - utf8_pos_;
130 if (space <= 0) return;
131 Vector<char> buffer(utf8_buffer_ + utf8_pos_, space);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000132 int size = SNPrintF(buffer, "%x", n);
Ben Murdoch257744e2011-11-30 15:57:28 +0000133 if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
134 utf8_pos_ += size;
135 }
136 }
137
138 const char* get() { return utf8_buffer_; }
139 int size() const { return utf8_pos_; }
140
141 private:
142 static const int kUtf8BufferSize = 512;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 static const int kUtf16BufferSize = kUtf8BufferSize;
Ben Murdoch257744e2011-11-30 15:57:28 +0000144
145 int utf8_pos_;
146 char utf8_buffer_[kUtf8BufferSize];
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100147 uc16 utf16_buffer[kUtf16BufferSize];
Ben Murdoch257744e2011-11-30 15:57:28 +0000148};
149
150
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151CodeEventLogger::CodeEventLogger() : name_buffer_(new NameBuffer) { }
152
153CodeEventLogger::~CodeEventLogger() { delete name_buffer_; }
154
Ben Murdoch61f157c2016-09-16 13:49:30 +0100155void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100156 AbstractCode* code, const char* comment) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157 name_buffer_->Init(tag);
158 name_buffer_->AppendBytes(comment);
159 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
160}
161
Ben Murdoch61f157c2016-09-16 13:49:30 +0100162void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100163 AbstractCode* code, Name* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 name_buffer_->Init(tag);
165 name_buffer_->AppendName(name);
166 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
167}
168
Ben Murdoch61f157c2016-09-16 13:49:30 +0100169void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100170 AbstractCode* code,
Ben Murdochc5610432016-08-08 18:44:38 +0100171 SharedFunctionInfo* shared, Name* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000172 name_buffer_->Init(tag);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173 name_buffer_->AppendBytes(ComputeMarker(shared, code));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174 name_buffer_->AppendName(name);
175 LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
176}
177
Ben Murdoch61f157c2016-09-16 13:49:30 +0100178void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100179 AbstractCode* code,
Ben Murdochc5610432016-08-08 18:44:38 +0100180 SharedFunctionInfo* shared, Name* source,
Ben Murdochda12d292016-06-02 14:46:10 +0100181 int line, int column) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000182 name_buffer_->Init(tag);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 name_buffer_->AppendBytes(ComputeMarker(shared, code));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 name_buffer_->AppendString(shared->DebugName());
185 name_buffer_->AppendByte(' ');
186 if (source->IsString()) {
187 name_buffer_->AppendString(String::cast(source));
188 } else {
189 name_buffer_->AppendBytes("symbol(hash ");
190 name_buffer_->AppendHex(Name::cast(source)->Hash());
191 name_buffer_->AppendByte(')');
192 }
193 name_buffer_->AppendByte(':');
194 name_buffer_->AppendInt(line);
195 LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
196}
197
Ben Murdoch61f157c2016-09-16 13:49:30 +0100198void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +0100199 AbstractCode* code, int args_count) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200 name_buffer_->Init(tag);
201 name_buffer_->AppendInt(args_count);
202 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
203}
204
Ben Murdochda12d292016-06-02 14:46:10 +0100205void CodeEventLogger::RegExpCodeCreateEvent(AbstractCode* code,
206 String* source) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100207 name_buffer_->Init(CodeEventListener::REG_EXP_TAG);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208 name_buffer_->AppendString(source);
209 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
210}
211
212
213// Linux perf tool logging support
214class PerfBasicLogger : public CodeEventLogger {
215 public:
216 PerfBasicLogger();
Ben Murdochda12d292016-06-02 14:46:10 +0100217 ~PerfBasicLogger() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218
Ben Murdochda12d292016-06-02 14:46:10 +0100219 void CodeMoveEvent(AbstractCode* from, Address to) override {}
220 void CodeDisableOptEvent(AbstractCode* code,
221 SharedFunctionInfo* shared) override {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222
223 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100224 void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo* shared,
225 const char* name, int length) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226
227 // Extension added to V8 log file name to get the low-level log name.
228 static const char kFilenameFormatString[];
229 static const int kFilenameBufferPadding;
230
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 FILE* perf_output_handle_;
232};
233
234const char PerfBasicLogger::kFilenameFormatString[] = "/tmp/perf-%d.map";
235// Extra space for the PID in the filename
236const int PerfBasicLogger::kFilenameBufferPadding = 16;
237
238PerfBasicLogger::PerfBasicLogger()
239 : perf_output_handle_(NULL) {
240 // Open the perf JIT dump file.
241 int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
242 ScopedVector<char> perf_dump_name(bufferSize);
243 int size = SNPrintF(
244 perf_dump_name,
245 kFilenameFormatString,
246 base::OS::GetCurrentProcessId());
247 CHECK_NE(size, -1);
248 perf_output_handle_ =
249 base::OS::FOpen(perf_dump_name.start(), base::OS::LogFileOpenMode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000250 CHECK_NOT_NULL(perf_output_handle_);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100251 setvbuf(perf_output_handle_, NULL, _IOLBF, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252}
253
254
255PerfBasicLogger::~PerfBasicLogger() {
256 fclose(perf_output_handle_);
257 perf_output_handle_ = NULL;
258}
259
Ben Murdochda12d292016-06-02 14:46:10 +0100260void PerfBasicLogger::LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
261 const char* name, int length) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262 if (FLAG_perf_basic_prof_only_functions &&
Ben Murdochda12d292016-06-02 14:46:10 +0100263 (code->kind() != AbstractCode::FUNCTION &&
264 code->kind() != AbstractCode::INTERPRETED_FUNCTION &&
265 code->kind() != AbstractCode::OPTIMIZED_FUNCTION)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266 return;
267 }
268
Ben Murdochc5610432016-08-08 18:44:38 +0100269 // Linux perf expects hex literals without a leading 0x, while some
270 // implementations of printf might prepend one when using the %p format
271 // for pointers, leading to wrongly formatted JIT symbols maps.
272 //
273 // Instead, we use V8PRIxPTR format string and cast pointer to uintpr_t,
274 // so that we have control over the exact output format.
275 base::OS::FPrint(perf_output_handle_, "%" V8PRIxPTR " %x %.*s\n",
276 reinterpret_cast<uintptr_t>(code->instruction_start()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000277 code->instruction_size(), length, name);
278}
279
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000280// Low-level logging support.
281#define LL_LOG(Call) if (ll_logger_) ll_logger_->Call;
282
283class LowLevelLogger : public CodeEventLogger {
284 public:
285 explicit LowLevelLogger(const char* file_name);
Ben Murdochda12d292016-06-02 14:46:10 +0100286 ~LowLevelLogger() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287
Ben Murdochda12d292016-06-02 14:46:10 +0100288 void CodeMoveEvent(AbstractCode* from, Address to) override;
289 void CodeDisableOptEvent(AbstractCode* code,
290 SharedFunctionInfo* shared) override {}
291 void SnapshotPositionEvent(HeapObject* obj, int pos);
292 void CodeMovingGCEvent() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293
294 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100295 void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo* shared,
296 const char* name, int length) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297
298 // Low-level profiling event structures.
299 struct CodeCreateStruct {
300 static const char kTag = 'C';
301
302 int32_t name_size;
303 Address code_address;
304 int32_t code_size;
305 };
306
307
308 struct CodeMoveStruct {
309 static const char kTag = 'M';
310
311 Address from_address;
312 Address to_address;
313 };
314
315
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000316 static const char kCodeMovingGCTag = 'G';
317
318
319 // Extension added to V8 log file name to get the low-level log name.
320 static const char kLogExt[];
321
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000322 void LogCodeInfo();
323 void LogWriteBytes(const char* bytes, int size);
324
325 template <typename T>
326 void LogWriteStruct(const T& s) {
327 char tag = T::kTag;
328 LogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag));
329 LogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s));
330 }
331
332 FILE* ll_output_handle_;
333};
334
335const char LowLevelLogger::kLogExt[] = ".ll";
336
337LowLevelLogger::LowLevelLogger(const char* name)
338 : ll_output_handle_(NULL) {
339 // Open the low-level log file.
340 size_t len = strlen(name);
341 ScopedVector<char> ll_name(static_cast<int>(len + sizeof(kLogExt)));
342 MemCopy(ll_name.start(), name, len);
343 MemCopy(ll_name.start() + len, kLogExt, sizeof(kLogExt));
344 ll_output_handle_ =
345 base::OS::FOpen(ll_name.start(), base::OS::LogFileOpenMode);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100346 setvbuf(ll_output_handle_, NULL, _IOLBF, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000347
348 LogCodeInfo();
349}
350
351
352LowLevelLogger::~LowLevelLogger() {
353 fclose(ll_output_handle_);
354 ll_output_handle_ = NULL;
355}
356
357
358void LowLevelLogger::LogCodeInfo() {
359#if V8_TARGET_ARCH_IA32
360 const char arch[] = "ia32";
361#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
362 const char arch[] = "x64";
363#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
364 const char arch[] = "x32";
365#elif V8_TARGET_ARCH_ARM
366 const char arch[] = "arm";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000367#elif V8_TARGET_ARCH_PPC
368 const char arch[] = "ppc";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369#elif V8_TARGET_ARCH_MIPS
370 const char arch[] = "mips";
371#elif V8_TARGET_ARCH_X87
372 const char arch[] = "x87";
373#elif V8_TARGET_ARCH_ARM64
374 const char arch[] = "arm64";
Ben Murdochda12d292016-06-02 14:46:10 +0100375#elif V8_TARGET_ARCH_S390
376 const char arch[] = "s390";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377#else
378 const char arch[] = "unknown";
379#endif
380 LogWriteBytes(arch, sizeof(arch));
381}
382
Ben Murdochda12d292016-06-02 14:46:10 +0100383void LowLevelLogger::LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
384 const char* name, int length) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000385 CodeCreateStruct event;
386 event.name_size = length;
387 event.code_address = code->instruction_start();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388 event.code_size = code->instruction_size();
389 LogWriteStruct(event);
390 LogWriteBytes(name, length);
391 LogWriteBytes(
392 reinterpret_cast<const char*>(code->instruction_start()),
393 code->instruction_size());
394}
395
Ben Murdochda12d292016-06-02 14:46:10 +0100396void LowLevelLogger::CodeMoveEvent(AbstractCode* from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397 CodeMoveStruct event;
Ben Murdochda12d292016-06-02 14:46:10 +0100398 event.from_address = from->instruction_start();
399 size_t header_size = from->instruction_start() - from->address();
400 event.to_address = to + header_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000401 LogWriteStruct(event);
402}
403
404
405void LowLevelLogger::LogWriteBytes(const char* bytes, int size) {
406 size_t rv = fwrite(bytes, 1, size, ll_output_handle_);
407 DCHECK(static_cast<size_t>(size) == rv);
408 USE(rv);
409}
410
411
412void LowLevelLogger::CodeMovingGCEvent() {
413 const char tag = kCodeMovingGCTag;
414
415 LogWriteBytes(&tag, sizeof(tag));
416}
417
418
419#define JIT_LOG(Call) if (jit_logger_) jit_logger_->Call;
420
421
422class JitLogger : public CodeEventLogger {
423 public:
424 explicit JitLogger(JitCodeEventHandler code_event_handler);
425
Ben Murdochda12d292016-06-02 14:46:10 +0100426 void CodeMoveEvent(AbstractCode* from, Address to) override;
427 void CodeDisableOptEvent(AbstractCode* code,
428 SharedFunctionInfo* shared) override {}
429 void AddCodeLinePosInfoEvent(void* jit_handler_data, int pc_offset,
430 int position,
431 JitCodeEvent::PositionType position_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432
433 void* StartCodePosInfoEvent();
Ben Murdochda12d292016-06-02 14:46:10 +0100434 void EndCodePosInfoEvent(AbstractCode* code, void* jit_handler_data);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000435
436 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100437 void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo* shared,
438 const char* name, int length) override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000439
440 JitCodeEventHandler code_event_handler_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 base::Mutex logger_mutex_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000442};
443
444
445JitLogger::JitLogger(JitCodeEventHandler code_event_handler)
446 : code_event_handler_(code_event_handler) {
447}
448
Ben Murdochda12d292016-06-02 14:46:10 +0100449void JitLogger::LogRecordedBuffer(AbstractCode* code,
450 SharedFunctionInfo* shared, const char* name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451 int length) {
452 JitCodeEvent event;
453 memset(&event, 0, sizeof(event));
454 event.type = JitCodeEvent::CODE_ADDED;
455 event.code_start = code->instruction_start();
456 event.code_len = code->instruction_size();
457 Handle<SharedFunctionInfo> shared_function_handle;
458 if (shared && shared->script()->IsScript()) {
459 shared_function_handle = Handle<SharedFunctionInfo>(shared);
460 }
461 event.script = ToApiHandle<v8::UnboundScript>(shared_function_handle);
462 event.name.str = name;
463 event.name.len = length;
464 code_event_handler_(&event);
465}
466
Ben Murdochda12d292016-06-02 14:46:10 +0100467void JitLogger::CodeMoveEvent(AbstractCode* from, Address to) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000468 base::LockGuard<base::Mutex> guard(&logger_mutex_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000469
470 JitCodeEvent event;
471 event.type = JitCodeEvent::CODE_MOVED;
Ben Murdochda12d292016-06-02 14:46:10 +0100472 event.code_start = from->instruction_start();
473 event.code_len = from->instruction_size();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000474
475 // Calculate the header size.
Ben Murdochda12d292016-06-02 14:46:10 +0100476 const size_t header_size = from->instruction_start() - from->address();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000477
478 // Calculate the new start address of the instructions.
Ben Murdochda12d292016-06-02 14:46:10 +0100479 event.new_code_start = to + header_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000480
481 code_event_handler_(&event);
482}
483
484void JitLogger::AddCodeLinePosInfoEvent(
485 void* jit_handler_data,
486 int pc_offset,
487 int position,
488 JitCodeEvent::PositionType position_type) {
489 JitCodeEvent event;
490 memset(&event, 0, sizeof(event));
491 event.type = JitCodeEvent::CODE_ADD_LINE_POS_INFO;
492 event.user_data = jit_handler_data;
493 event.line_info.offset = pc_offset;
494 event.line_info.pos = position;
495 event.line_info.position_type = position_type;
496
497 code_event_handler_(&event);
498}
499
500
501void* JitLogger::StartCodePosInfoEvent() {
502 JitCodeEvent event;
503 memset(&event, 0, sizeof(event));
504 event.type = JitCodeEvent::CODE_START_LINE_INFO_RECORDING;
505
506 code_event_handler_(&event);
507 return event.user_data;
508}
509
Ben Murdochda12d292016-06-02 14:46:10 +0100510void JitLogger::EndCodePosInfoEvent(AbstractCode* code,
511 void* jit_handler_data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000512 JitCodeEvent event;
513 memset(&event, 0, sizeof(event));
514 event.type = JitCodeEvent::CODE_END_LINE_INFO_RECORDING;
515 event.code_start = code->instruction_start();
516 event.user_data = jit_handler_data;
517
518 code_event_handler_(&event);
519}
520
521
Ben Murdoch61f157c2016-09-16 13:49:30 +0100522// TODO(lpy): Keeping sampling thread inside V8 is a workaround currently,
523// the reason is to reduce code duplication during migration to sampler library,
524// sampling thread, as well as the sampler, will be moved to D8 eventually.
525class SamplingThread : public base::Thread {
526 public:
527 static const int kSamplingThreadStackSize = 64 * KB;
528
529 SamplingThread(sampler::Sampler* sampler, int interval)
530 : base::Thread(base::Thread::Options("SamplingThread",
531 kSamplingThreadStackSize)),
532 sampler_(sampler),
533 interval_(interval) {}
534 void Run() override {
535 while (sampler_->IsProfiling()) {
536 sampler_->DoSample();
537 base::OS::Sleep(base::TimeDelta::FromMilliseconds(interval_));
538 }
539 }
540
541 private:
542 sampler::Sampler* sampler_;
543 const int interval_;
544};
545
546
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547// The Profiler samples pc and sp values for the main thread.
548// Each sample is appended to a circular buffer.
549// An independent thread removes data and writes it to the log.
550// This design minimizes the time spent in the sampler.
551//
552class Profiler: public base::Thread {
553 public:
554 explicit Profiler(Isolate* isolate);
555 void Engage();
556 void Disengage();
557
558 // Inserts collected profiling data into buffer.
559 void Insert(TickSample* sample) {
560 if (paused_)
561 return;
562
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400563 if (Succ(head_) == static_cast<int>(base::NoBarrier_Load(&tail_))) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564 overflow_ = true;
565 } else {
566 buffer_[head_] = *sample;
567 head_ = Succ(head_);
568 buffer_semaphore_.Signal(); // Tell we have an element.
569 }
570 }
571
572 virtual void Run();
573
574 // Pause and Resume TickSample data collection.
575 void pause() { paused_ = true; }
576 void resume() { paused_ = false; }
577
578 private:
579 // Waits for a signal and removes profiling data.
580 bool Remove(TickSample* sample) {
581 buffer_semaphore_.Wait(); // Wait for an element.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400582 *sample = buffer_[base::NoBarrier_Load(&tail_)];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 bool result = overflow_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400584 base::NoBarrier_Store(&tail_, static_cast<base::Atomic32>(
585 Succ(base::NoBarrier_Load(&tail_))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000586 overflow_ = false;
587 return result;
588 }
589
590 // Returns the next index in the cyclic buffer.
591 int Succ(int index) { return (index + 1) % kBufferSize; }
592
593 Isolate* isolate_;
594 // Cyclic buffer for communicating profiling samples
595 // between the signal handler and the worker thread.
596 static const int kBufferSize = 128;
597 TickSample buffer_[kBufferSize]; // Buffer storage.
598 int head_; // Index to the buffer head.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400599 base::Atomic32 tail_; // Index to the buffer tail.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600 bool overflow_; // Tell whether a buffer overflow has occurred.
601 // Sempahore used for buffer synchronization.
602 base::Semaphore buffer_semaphore_;
603
604 // Tells whether profiler is engaged, that is, processing thread is stated.
605 bool engaged_;
606
607 // Tells whether worker thread should continue running.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608 base::Atomic32 running_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609
610 // Tells whether we are currently recording tick samples.
611 bool paused_;
612};
613
614
615//
616// Ticker used to provide ticks to the profiler and the sliding state
617// window.
618//
Ben Murdoch61f157c2016-09-16 13:49:30 +0100619class Ticker: public sampler::Sampler {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620 public:
621 Ticker(Isolate* isolate, int interval):
Ben Murdoch61f157c2016-09-16 13:49:30 +0100622 sampler::Sampler(reinterpret_cast<v8::Isolate*>(isolate)),
623 profiler_(NULL),
624 sampling_thread_(new SamplingThread(this, interval)) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625
Ben Murdoch61f157c2016-09-16 13:49:30 +0100626 ~Ticker() {
627 if (IsActive()) Stop();
628 delete sampling_thread_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 }
630
631 void SetProfiler(Profiler* profiler) {
632 DCHECK(profiler_ == NULL);
633 profiler_ = profiler;
634 IncreaseProfilingDepth();
635 if (!IsActive()) Start();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100636 sampling_thread_->StartSynchronously();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000637 }
638
639 void ClearProfiler() {
640 profiler_ = NULL;
641 if (IsActive()) Stop();
642 DecreaseProfilingDepth();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100643 sampling_thread_->Join();
644 }
645
646 void SampleStack(const v8::RegisterState& state) override {
647 v8::Isolate* v8_isolate = isolate();
648 Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
649#if defined(USE_SIMULATOR)
650 SimulatorHelper::FillRegisters(isolate,
651 const_cast<v8::RegisterState*>(&state));
652#endif
653 TickSample* sample = isolate->cpu_profiler()->StartTickSample();
654 TickSample sample_obj;
655 if (sample == NULL) sample = &sample_obj;
656 sample->Init(isolate, state, TickSample::kIncludeCEntryFrame, true);
657 if (is_counting_samples_ && !sample->timestamp.IsNull()) {
658 if (sample->state == JS) ++js_sample_count_;
659 if (sample->state == EXTERNAL) ++external_sample_count_;
660 }
661 if (profiler_) profiler_->Insert(sample);
662 if (sample != &sample_obj) {
663 isolate->cpu_profiler()->FinishTickSample();
664 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000665 }
666
667 private:
668 Profiler* profiler_;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100669 SamplingThread* sampling_thread_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000670};
671
672
673//
674// Profiler implementation.
675//
676Profiler::Profiler(Isolate* isolate)
677 : base::Thread(Options("v8:Profiler")),
678 isolate_(isolate),
679 head_(0),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000680 overflow_(false),
681 buffer_semaphore_(0),
682 engaged_(false),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400683 paused_(false) {
684 base::NoBarrier_Store(&tail_, 0);
685 base::NoBarrier_Store(&running_, 0);
686}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000687
688
689void Profiler::Engage() {
690 if (engaged_) return;
691 engaged_ = true;
692
693 std::vector<base::OS::SharedLibraryAddress> addresses =
694 base::OS::GetSharedLibraryAddresses();
695 for (size_t i = 0; i < addresses.size(); ++i) {
Ben Murdochc5610432016-08-08 18:44:38 +0100696 LOG(isolate_,
697 SharedLibraryEvent(addresses[i].library_path, addresses[i].start,
698 addresses[i].end, addresses[i].aslr_slide));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699 }
700
701 // Start thread processing the profiler buffer.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400702 base::NoBarrier_Store(&running_, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000703 Start();
704
705 // Register to get ticks.
706 Logger* logger = isolate_->logger();
707 logger->ticker_->SetProfiler(this);
708
709 logger->ProfilerBeginEvent();
710}
711
712
713void Profiler::Disengage() {
714 if (!engaged_) return;
715
716 // Stop receiving ticks.
717 isolate_->logger()->ticker_->ClearProfiler();
718
719 // Terminate the worker thread by setting running_ to false,
720 // inserting a fake element in the queue and then wait for
721 // the thread to terminate.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400722 base::NoBarrier_Store(&running_, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000723 TickSample sample;
724 // Reset 'paused_' flag, otherwise semaphore may not be signalled.
725 resume();
726 Insert(&sample);
727 Join();
728
729 LOG(isolate_, UncheckedStringEvent("profiler", "end"));
730}
731
732
733void Profiler::Run() {
734 TickSample sample;
735 bool overflow = Remove(&sample);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400736 while (base::NoBarrier_Load(&running_)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737 LOG(isolate_, TickEvent(&sample, overflow));
738 overflow = Remove(&sample);
739 }
740}
741
742
743//
744// Logger class implementation.
745//
746
747Logger::Logger(Isolate* isolate)
Ben Murdochda12d292016-06-02 14:46:10 +0100748 : isolate_(isolate),
749 ticker_(NULL),
750 profiler_(NULL),
751 log_events_(NULL),
752 is_logging_(false),
753 log_(new Log(this)),
754 perf_basic_logger_(NULL),
755 perf_jit_logger_(NULL),
756 ll_logger_(NULL),
757 jit_logger_(NULL),
758 listeners_(5),
759 is_initialized_(false) {}
Ben Murdoch257744e2011-11-30 15:57:28 +0000760
Steve Block44f0eee2011-05-26 01:26:41 +0100761Logger::~Logger() {
762 delete log_;
763}
Steve Blocka7e24c12009-10-30 11:49:00 +0000764
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000765void Logger::addCodeEventListener(CodeEventListener* listener) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100766 bool result = isolate_->code_event_dispatcher()->AddListener(listener);
767 USE(result);
768 DCHECK(result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000769}
770
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000771void Logger::removeCodeEventListener(CodeEventListener* listener) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100772 isolate_->code_event_dispatcher()->RemoveListener(listener);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000773}
774
Steve Blocka7e24c12009-10-30 11:49:00 +0000775void Logger::ProfilerBeginEvent() {
Steve Block44f0eee2011-05-26 01:26:41 +0100776 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000777 Log::MessageBuilder msg(log_);
778 msg.Append("profiler,\"begin\",%d", kSamplingIntervalMs);
Steve Blocka7e24c12009-10-30 11:49:00 +0000779 msg.WriteToLogFile();
780}
781
Steve Blocka7e24c12009-10-30 11:49:00 +0000782
Steve Blocka7e24c12009-10-30 11:49:00 +0000783void Logger::StringEvent(const char* name, const char* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000784 if (FLAG_log) UncheckedStringEvent(name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000785}
786
787
Steve Blocka7e24c12009-10-30 11:49:00 +0000788void Logger::UncheckedStringEvent(const char* name, const char* value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100789 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000790 Log::MessageBuilder msg(log_);
791 msg.Append("%s,\"%s\"", name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000792 msg.WriteToLogFile();
793}
Steve Blocka7e24c12009-10-30 11:49:00 +0000794
795
796void Logger::IntEvent(const char* name, int value) {
Steve Block6ded16b2010-05-10 14:33:55 +0100797 if (FLAG_log) UncheckedIntEvent(name, value);
Steve Block6ded16b2010-05-10 14:33:55 +0100798}
799
800
Ben Murdochf87a2032010-10-22 12:50:53 +0100801void Logger::IntPtrTEvent(const char* name, intptr_t value) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100802 if (FLAG_log) UncheckedIntPtrTEvent(name, value);
Ben Murdochf87a2032010-10-22 12:50:53 +0100803}
804
805
Steve Block6ded16b2010-05-10 14:33:55 +0100806void Logger::UncheckedIntEvent(const char* name, int value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100807 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000808 Log::MessageBuilder msg(log_);
809 msg.Append("%s,%d", name, value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000810 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000811}
812
813
Ben Murdochf87a2032010-10-22 12:50:53 +0100814void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
Steve Block44f0eee2011-05-26 01:26:41 +0100815 if (!log_->IsEnabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000816 Log::MessageBuilder msg(log_);
Ben Murdochc5610432016-08-08 18:44:38 +0100817 msg.Append("%s,%" V8PRIdPTR, name, value);
Ben Murdochf87a2032010-10-22 12:50:53 +0100818 msg.WriteToLogFile();
819}
Ben Murdochf87a2032010-10-22 12:50:53 +0100820
821
Steve Blocka7e24c12009-10-30 11:49:00 +0000822void Logger::HandleEvent(const char* name, Object** location) {
Steve Block44f0eee2011-05-26 01:26:41 +0100823 if (!log_->IsEnabled() || !FLAG_log_handles) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000824 Log::MessageBuilder msg(log_);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100825 msg.Append("%s,%p", name, static_cast<void*>(location));
Steve Blocka7e24c12009-10-30 11:49:00 +0000826 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000827}
828
829
Steve Blocka7e24c12009-10-30 11:49:00 +0000830// ApiEvent is private so all the calls come from the Logger class. It is the
831// caller's responsibility to ensure that log is enabled and that
832// FLAG_log_api is true.
833void Logger::ApiEvent(const char* format, ...) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000834 DCHECK(log_->IsEnabled() && FLAG_log_api);
835 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000836 va_list ap;
837 va_start(ap, format);
838 msg.AppendVA(format, ap);
839 va_end(ap);
840 msg.WriteToLogFile();
841}
Steve Blocka7e24c12009-10-30 11:49:00 +0000842
843
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000844void Logger::ApiSecurityCheck() {
Steve Block44f0eee2011-05-26 01:26:41 +0100845 if (!log_->IsEnabled() || !FLAG_log_api) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000846 ApiEvent("api,check-security");
Steve Blocka7e24c12009-10-30 11:49:00 +0000847}
848
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000849void Logger::SharedLibraryEvent(const std::string& library_path,
Ben Murdochc5610432016-08-08 18:44:38 +0100850 uintptr_t start, uintptr_t end,
851 intptr_t aslr_slide) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852 if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853 Log::MessageBuilder msg(log_);
Ben Murdochc5610432016-08-08 18:44:38 +0100854 msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR
855 ",%" V8PRIdPTR,
856 library_path.c_str(), start, end, aslr_slide);
Steve Blocka7e24c12009-10-30 11:49:00 +0000857 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000858}
859
860
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000861void Logger::CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000862 if (!log_->IsEnabled() || !FLAG_log_internal_timer_events) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863 Log::MessageBuilder msg(log_);
864 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
Ben Murdochc5610432016-08-08 18:44:38 +0100865 msg.Append("code-deopt,%d,%d", since_epoch, code->CodeSize());
Steve Blocka7e24c12009-10-30 11:49:00 +0000866 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000867}
868
869
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000870void Logger::CurrentTimeEvent() {
871 if (!log_->IsEnabled()) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000872 DCHECK(FLAG_log_timer_events || FLAG_prof_cpp);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000873 Log::MessageBuilder msg(log_);
874 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
Ben Murdochc5610432016-08-08 18:44:38 +0100875 msg.Append("current-time,%d", since_epoch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000876 msg.WriteToLogFile();
877}
878
879
880void Logger::TimerEvent(Logger::StartEnd se, const char* name) {
881 if (!log_->IsEnabled()) return;
882 DCHECK(FLAG_log_internal_timer_events);
883 Log::MessageBuilder msg(log_);
884 int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
885 const char* format = (se == START) ? "timer-event-start,\"%s\",%ld"
886 : "timer-event-end,\"%s\",%ld";
887 msg.Append(format, name, since_epoch);
888 msg.WriteToLogFile();
889}
890
891
892void Logger::EnterExternal(Isolate* isolate) {
893 LOG(isolate, TimerEvent(START, TimerEventExternal::name()));
894 DCHECK(isolate->current_vm_state() == JS);
895 isolate->set_current_vm_state(EXTERNAL);
896}
897
898
899void Logger::LeaveExternal(Isolate* isolate) {
900 LOG(isolate, TimerEvent(END, TimerEventExternal::name()));
901 DCHECK(isolate->current_vm_state() == EXTERNAL);
902 isolate->set_current_vm_state(JS);
903}
904
905
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906template <class TimerEvent>
907void TimerEventScope<TimerEvent>::LogTimerEvent(Logger::StartEnd se) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400908 Logger::CallEventLogger(isolate_, TimerEvent::name(), se,
909 TimerEvent::expose_to_api());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910}
911
912
913// Instantiate template methods.
914#define V(TimerName, expose) \
915 template void TimerEventScope<TimerEvent##TimerName>::LogTimerEvent( \
916 Logger::StartEnd se);
917TIMER_EVENTS_LIST(V)
918#undef V
919
920
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000921namespace {
922// Emits the source code of a regexp. Used by regexp events.
923void LogRegExpSource(Handle<JSRegExp> regexp, Isolate* isolate,
924 Log::MessageBuilder* msg) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000925 // Prints "/" + re.source + "/" +
926 // (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
Steve Blocka7e24c12009-10-30 11:49:00 +0000927
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000928 Handle<Object> source =
Ben Murdochda12d292016-06-02 14:46:10 +0100929 JSReceiver::GetProperty(isolate, regexp, "source").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000930 if (!source->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 msg->Append("no source");
Steve Blocka7e24c12009-10-30 11:49:00 +0000932 return;
933 }
934
935 switch (regexp->TypeTag()) {
936 case JSRegExp::ATOM:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000937 msg->Append('a');
Steve Blocka7e24c12009-10-30 11:49:00 +0000938 break;
939 default:
940 break;
941 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000942 msg->Append('/');
943 msg->AppendDetailed(*Handle<String>::cast(source), false);
944 msg->Append('/');
Steve Blocka7e24c12009-10-30 11:49:00 +0000945
946 // global flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000947 Handle<Object> global =
Ben Murdochda12d292016-06-02 14:46:10 +0100948 JSReceiver::GetProperty(isolate, regexp, "global").ToHandleChecked();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100949 if (global->IsTrue(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000950 msg->Append('g');
Steve Blocka7e24c12009-10-30 11:49:00 +0000951 }
952 // ignorecase flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000953 Handle<Object> ignorecase =
Ben Murdochda12d292016-06-02 14:46:10 +0100954 JSReceiver::GetProperty(isolate, regexp, "ignoreCase").ToHandleChecked();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100955 if (ignorecase->IsTrue(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000956 msg->Append('i');
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 }
958 // multiline flag
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000959 Handle<Object> multiline =
Ben Murdochda12d292016-06-02 14:46:10 +0100960 JSReceiver::GetProperty(isolate, regexp, "multiline").ToHandleChecked();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100961 if (multiline->IsTrue(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000962 msg->Append('m');
Steve Blocka7e24c12009-10-30 11:49:00 +0000963 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000964}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000965} // namespace
Steve Blocka7e24c12009-10-30 11:49:00 +0000966
967
968void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
Steve Block44f0eee2011-05-26 01:26:41 +0100969 if (!log_->IsEnabled() || !FLAG_log_regexp) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000970 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000971 msg.Append("regexp-compile,");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000972 LogRegExpSource(regexp, isolate_, &msg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000973 msg.Append(in_cache ? ",hit" : ",miss");
Steve Blocka7e24c12009-10-30 11:49:00 +0000974 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000975}
976
977
Steve Blocka7e24c12009-10-30 11:49:00 +0000978void Logger::ApiNamedPropertyAccess(const char* tag,
979 JSObject* holder,
980 Object* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000981 DCHECK(name->IsName());
Steve Block44f0eee2011-05-26 01:26:41 +0100982 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000983 String* class_name_obj = holder->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000984 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +0000985 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000986 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000987 base::SmartArrayPointer<char> property_name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000988 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
989 ApiEvent("api,%s,\"%s\",\"%s\"", tag, class_name.get(),
990 property_name.get());
991 } else {
992 Symbol* symbol = Symbol::cast(name);
993 uint32_t hash = symbol->Hash();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100994 if (symbol->name()->IsUndefined(symbol->GetIsolate())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995 ApiEvent("api,%s,\"%s\",symbol(hash %x)", tag, class_name.get(), hash);
996 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 base::SmartArrayPointer<char> str =
998 String::cast(symbol->name())
999 ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000 ApiEvent("api,%s,\"%s\",symbol(\"%s\" hash %x)", tag, class_name.get(),
1001 str.get(), hash);
1002 }
1003 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001004}
1005
1006void Logger::ApiIndexedPropertyAccess(const char* tag,
1007 JSObject* holder,
1008 uint32_t index) {
Steve Block44f0eee2011-05-26 01:26:41 +01001009 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001010 String* class_name_obj = holder->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +00001012 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001013 ApiEvent("api,%s,\"%s\",%u", tag, class_name.get(), index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001014}
1015
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001016
Steve Blocka7e24c12009-10-30 11:49:00 +00001017void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
Steve Block44f0eee2011-05-26 01:26:41 +01001018 if (!log_->IsEnabled() || !FLAG_log_api) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001019 String* class_name_obj = object->class_name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001020 base::SmartArrayPointer<char> class_name =
Steve Blocka7e24c12009-10-30 11:49:00 +00001021 class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001022 ApiEvent("api,%s,\"%s\"", tag, class_name.get());
Steve Blocka7e24c12009-10-30 11:49:00 +00001023}
1024
1025
1026void Logger::ApiEntryCall(const char* name) {
Steve Block44f0eee2011-05-26 01:26:41 +01001027 if (!log_->IsEnabled() || !FLAG_log_api) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001028 ApiEvent("api,%s", name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001029}
1030
1031
1032void Logger::NewEvent(const char* name, void* object, size_t size) {
Steve Block44f0eee2011-05-26 01:26:41 +01001033 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001034 Log::MessageBuilder msg(log_);
Ben Murdochc5610432016-08-08 18:44:38 +01001035 msg.Append("new,%s,%p,%u", name, object, static_cast<unsigned int>(size));
Steve Blocka7e24c12009-10-30 11:49:00 +00001036 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001037}
1038
1039
1040void Logger::DeleteEvent(const char* name, void* object) {
Steve Block44f0eee2011-05-26 01:26:41 +01001041 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001042 Log::MessageBuilder msg(log_);
Ben Murdochc5610432016-08-08 18:44:38 +01001043 msg.Append("delete,%s,%p", name, object);
Steve Blocka7e24c12009-10-30 11:49:00 +00001044 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001045}
1046
1047
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048void Logger::CallbackEventInternal(const char* prefix, Name* name,
Steve Blockd0582a62009-12-15 09:54:21 +00001049 Address entry_point) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001050 if (!FLAG_log_code || !log_->IsEnabled()) return;
1051 Log::MessageBuilder msg(log_);
1052 msg.Append("%s,%s,-2,",
Ben Murdoch61f157c2016-09-16 13:49:30 +01001053 kLogEventsNames[CodeEventListener::CODE_CREATION_EVENT],
1054 kLogEventsNames[CodeEventListener::CALLBACK_TAG]);
Steve Blockd0582a62009-12-15 09:54:21 +00001055 msg.AppendAddress(entry_point);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001057 base::SmartArrayPointer<char> str =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001058 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1059 msg.Append(",1,\"%s%s\"", prefix, str.get());
1060 } else {
1061 Symbol* symbol = Symbol::cast(name);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001062 if (symbol->name()->IsUndefined(symbol->GetIsolate())) {
Ben Murdochc5610432016-08-08 18:44:38 +01001063 msg.Append(",1,symbol(hash %x)", symbol->Hash());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001064 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001065 base::SmartArrayPointer<char> str =
1066 String::cast(symbol->name())
1067 ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochc5610432016-08-08 18:44:38 +01001068 msg.Append(",1,symbol(\"%s%s\" hash %x)", prefix, str.get(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001069 symbol->Hash());
1070 }
1071 }
Steve Blockd0582a62009-12-15 09:54:21 +00001072 msg.WriteToLogFile();
1073}
Steve Blockd0582a62009-12-15 09:54:21 +00001074
1075
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001076void Logger::CallbackEvent(Name* name, Address entry_point) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001077 CallbackEventInternal("", name, entry_point);
Steve Blockd0582a62009-12-15 09:54:21 +00001078}
1079
1080
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001081void Logger::GetterCallbackEvent(Name* name, Address entry_point) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001082 CallbackEventInternal("get ", name, entry_point);
Steve Blockd0582a62009-12-15 09:54:21 +00001083}
1084
1085
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001086void Logger::SetterCallbackEvent(Name* name, Address entry_point) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087 CallbackEventInternal("set ", name, entry_point);
1088}
1089
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001090static void AppendCodeCreateHeader(Log::MessageBuilder* msg,
Ben Murdoch61f157c2016-09-16 13:49:30 +01001091 CodeEventListener::LogEventsAndTags tag,
Ben Murdochda12d292016-06-02 14:46:10 +01001092 AbstractCode* code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001093 DCHECK(msg);
1094 msg->Append("%s,%s,%d,",
Ben Murdoch61f157c2016-09-16 13:49:30 +01001095 kLogEventsNames[CodeEventListener::CODE_CREATION_EVENT],
1096 kLogEventsNames[tag], code->kind());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001097 msg->AppendAddress(code->address());
1098 msg->Append(",%d,", code->ExecutableSize());
Steve Blockd0582a62009-12-15 09:54:21 +00001099}
1100
Ben Murdoch61f157c2016-09-16 13:49:30 +01001101void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
1102 AbstractCode* code, const char* comment) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001103 if (!is_logging_code_events()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001104 if (!FLAG_log_code || !log_->IsEnabled()) return;
1105 Log::MessageBuilder msg(log_);
1106 AppendCodeCreateHeader(&msg, tag, code);
1107 msg.AppendDoubleQuotedString(comment);
Steve Blocka7e24c12009-10-30 11:49:00 +00001108 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001109}
1110
Ben Murdoch61f157c2016-09-16 13:49:30 +01001111void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
1112 AbstractCode* code, Name* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001113 if (!is_logging_code_events()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001114 if (!FLAG_log_code || !log_->IsEnabled()) return;
1115 Log::MessageBuilder msg(log_);
1116 AppendCodeCreateHeader(&msg, tag, code);
1117 if (name->IsString()) {
1118 msg.Append('"');
1119 msg.AppendDetailed(String::cast(name), false);
1120 msg.Append('"');
1121 } else {
1122 msg.AppendSymbolName(Symbol::cast(name));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001123 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001124 msg.WriteToLogFile();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001125}
1126
Ben Murdoch61f157c2016-09-16 13:49:30 +01001127void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
1128 AbstractCode* code, SharedFunctionInfo* shared,
1129 Name* name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001130 if (!is_logging_code_events()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001131 if (!FLAG_log_code || !log_->IsEnabled()) return;
Ben Murdochda12d292016-06-02 14:46:10 +01001132 if (code == AbstractCode::cast(
1133 isolate_->builtins()->builtin(Builtins::kCompileLazy))) {
1134 return;
1135 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001136
1137 Log::MessageBuilder msg(log_);
1138 AppendCodeCreateHeader(&msg, tag, code);
1139 if (name->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140 base::SmartArrayPointer<char> str =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001141 String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1142 msg.Append("\"%s\"", str.get());
1143 } else {
1144 msg.AppendSymbolName(Symbol::cast(name));
1145 }
1146 msg.Append(',');
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001147 msg.AppendAddress(shared->address());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001148 msg.Append(",%s", ComputeMarker(shared, code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001149 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001150}
1151
1152
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001153// Although, it is possible to extract source and line from
1154// the SharedFunctionInfo object, we left it to caller
1155// to leave logging functions free from heap allocations.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001156void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
1157 AbstractCode* code, SharedFunctionInfo* shared,
1158 Name* source, int line, int column) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001159 if (!is_logging_code_events()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001160 if (!FLAG_log_code || !log_->IsEnabled()) return;
1161 Log::MessageBuilder msg(log_);
1162 AppendCodeCreateHeader(&msg, tag, code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001163 base::SmartArrayPointer<char> name =
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001164 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001165 msg.Append("\"%s ", name.get());
1166 if (source->IsString()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001167 base::SmartArrayPointer<char> sourcestr = String::cast(source)->ToCString(
1168 DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001169 msg.Append("%s", sourcestr.get());
1170 } else {
1171 msg.AppendSymbolName(Symbol::cast(source));
1172 }
1173 msg.Append(":%d:%d\",", line, column);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001174 msg.AppendAddress(shared->address());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001175 msg.Append(",%s", ComputeMarker(shared, code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001176 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001177}
1178
Ben Murdoch61f157c2016-09-16 13:49:30 +01001179void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
1180 AbstractCode* code, int args_count) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001181 if (!is_logging_code_events()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001182 if (!FLAG_log_code || !log_->IsEnabled()) return;
1183 Log::MessageBuilder msg(log_);
1184 AppendCodeCreateHeader(&msg, tag, code);
1185 msg.Append("\"args_count: %d\"", args_count);
1186 msg.WriteToLogFile();
1187}
1188
Ben Murdochda12d292016-06-02 14:46:10 +01001189void Logger::CodeDisableOptEvent(AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001190 SharedFunctionInfo* shared) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001191 if (!is_logging_code_events()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 if (!FLAG_log_code || !log_->IsEnabled()) return;
1193 Log::MessageBuilder msg(log_);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001194 msg.Append("%s,", kLogEventsNames[CodeEventListener::CODE_DISABLE_OPT_EVENT]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001195 base::SmartArrayPointer<char> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001196 shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1197 msg.Append("\"%s\",", name.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001198 msg.Append("\"%s\"", GetBailoutReason(shared->disable_optimization_reason()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001199 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001200}
1201
1202
Ben Murdochf87a2032010-10-22 12:50:53 +01001203void Logger::CodeMovingGCEvent() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001204 if (!is_logging_code_events()) return;
Ben Murdoch257744e2011-11-30 15:57:28 +00001205 if (!log_->IsEnabled() || !FLAG_ll_prof) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001206 base::OS::SignalCodeMovingGC();
Ben Murdochf87a2032010-10-22 12:50:53 +01001207}
1208
Ben Murdochda12d292016-06-02 14:46:10 +01001209void Logger::RegExpCodeCreateEvent(AbstractCode* code, String* source) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210 if (!is_logging_code_events()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001211 if (!FLAG_log_code || !log_->IsEnabled()) return;
1212 Log::MessageBuilder msg(log_);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001213 AppendCodeCreateHeader(&msg, CodeEventListener::REG_EXP_TAG, code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214 msg.Append('"');
Steve Blocka7e24c12009-10-30 11:49:00 +00001215 msg.AppendDetailed(source, false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001216 msg.Append('"');
Steve Blocka7e24c12009-10-30 11:49:00 +00001217 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001218}
1219
Ben Murdochda12d292016-06-02 14:46:10 +01001220void Logger::CodeMoveEvent(AbstractCode* from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001221 if (!is_logging_code_events()) return;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001222 MoveEventInternal(CodeEventListener::CODE_MOVE_EVENT, from->address(), to);
Steve Blocka7e24c12009-10-30 11:49:00 +00001223}
1224
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001225void Logger::CodeLinePosInfoAddPositionEvent(void* jit_handler_data,
Ben Murdochda12d292016-06-02 14:46:10 +01001226 int pc_offset, int position) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001227 JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1228 pc_offset,
1229 position,
1230 JitCodeEvent::POSITION));
1231}
1232
1233
1234void Logger::CodeLinePosInfoAddStatementPositionEvent(void* jit_handler_data,
1235 int pc_offset,
1236 int position) {
1237 JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1238 pc_offset,
1239 position,
1240 JitCodeEvent::STATEMENT_POSITION));
1241}
1242
1243
1244void Logger::CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder) {
1245 if (jit_logger_ != NULL) {
1246 pos_recorder->AttachJITHandlerData(jit_logger_->StartCodePosInfoEvent());
Ben Murdoch257744e2011-11-30 15:57:28 +00001247 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001248}
1249
Ben Murdochda12d292016-06-02 14:46:10 +01001250void Logger::CodeEndLinePosInfoRecordEvent(AbstractCode* code,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001251 void* jit_handler_data) {
1252 JIT_LOG(EndCodePosInfoEvent(code, jit_handler_data));
1253}
1254
1255
1256void Logger::CodeNameEvent(Address addr, int pos, const char* code_name) {
1257 if (code_name == NULL) return; // Not a code object.
1258 Log::MessageBuilder msg(log_);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001259 msg.Append("%s,%d,",
1260 kLogEventsNames[CodeEventListener::SNAPSHOT_CODE_NAME_EVENT], pos);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001261 msg.AppendDoubleQuotedString(code_name);
1262 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001263}
1264
1265
Steve Block44f0eee2011-05-26 01:26:41 +01001266void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001267 if (!is_logging_code_events()) return;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001268 MoveEventInternal(CodeEventListener::SHARED_FUNC_MOVE_EVENT, from, to);
Leon Clarked91b9f72010-01-27 17:25:45 +00001269}
1270
Ben Murdoch61f157c2016-09-16 13:49:30 +01001271void Logger::MoveEventInternal(CodeEventListener::LogEventsAndTags event,
1272 Address from, Address to) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001273 if (!FLAG_log_code || !log_->IsEnabled()) return;
1274 Log::MessageBuilder msg(log_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001275 msg.Append("%s,", kLogEventsNames[event]);
Leon Clarked91b9f72010-01-27 17:25:45 +00001276 msg.AppendAddress(from);
1277 msg.Append(',');
Ben Murdochb0fe1622011-05-05 13:52:32 +01001278 msg.AppendAddress(to);
Leon Clarked91b9f72010-01-27 17:25:45 +00001279 msg.WriteToLogFile();
1280}
Leon Clarked91b9f72010-01-27 17:25:45 +00001281
1282
Steve Blocka7e24c12009-10-30 11:49:00 +00001283void Logger::ResourceEvent(const char* name, const char* tag) {
Steve Block44f0eee2011-05-26 01:26:41 +01001284 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001285 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001286 msg.Append("%s,%s,", name, tag);
1287
1288 uint32_t sec, usec;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 if (base::OS::GetUserTime(&sec, &usec) != -1) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001290 msg.Append("%d,%d,", sec, usec);
1291 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001292 msg.Append("%.0f", base::OS::TimeCurrentMillis());
Steve Blocka7e24c12009-10-30 11:49:00 +00001293 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001294}
1295
1296
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001297void Logger::SuspectReadEvent(Name* name, Object* obj) {
Steve Block44f0eee2011-05-26 01:26:41 +01001298 if (!log_->IsEnabled() || !FLAG_log_suspect) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001299 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001300 String* class_name = obj->IsJSObject()
1301 ? JSObject::cast(obj)->class_name()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001302 : isolate_->heap()->empty_string();
Steve Blocka7e24c12009-10-30 11:49:00 +00001303 msg.Append("suspect-read,");
1304 msg.Append(class_name);
1305 msg.Append(',');
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001306 if (name->IsString()) {
1307 msg.Append('"');
1308 msg.Append(String::cast(name));
1309 msg.Append('"');
1310 } else {
1311 msg.AppendSymbolName(Symbol::cast(name));
1312 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001313 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001314}
1315
1316
1317void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
Steve Block44f0eee2011-05-26 01:26:41 +01001318 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001319 Log::MessageBuilder msg(log_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001320 // Using non-relative system time in order to be able to synchronize with
1321 // external memory profiling events (e.g. DOM memory size).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001322 msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f", space, kind,
1323 base::OS::TimeCurrentMillis());
Steve Blocka7e24c12009-10-30 11:49:00 +00001324 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001325}
1326
1327
1328void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
Steve Block44f0eee2011-05-26 01:26:41 +01001329 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001330 Log::MessageBuilder msg(log_);
1331 msg.Append("heap-sample-end,\"%s\",\"%s\"", space, kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00001332 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001333}
1334
1335
1336void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
Steve Block44f0eee2011-05-26 01:26:41 +01001337 if (!log_->IsEnabled() || !FLAG_log_gc) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001338 Log::MessageBuilder msg(log_);
1339 msg.Append("heap-sample-item,%s,%d,%d", type, number, bytes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001340 msg.WriteToLogFile();
Steve Block3ce2e202009-11-05 08:53:23 +00001341}
1342
1343
Steve Blocka7e24c12009-10-30 11:49:00 +00001344void Logger::DebugTag(const char* call_site_tag) {
Steve Block44f0eee2011-05-26 01:26:41 +01001345 if (!log_->IsEnabled() || !FLAG_log) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001346 Log::MessageBuilder msg(log_);
1347 msg.Append("debug-tag,%s", call_site_tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00001348 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001349}
1350
1351
1352void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
Steve Block44f0eee2011-05-26 01:26:41 +01001353 if (!log_->IsEnabled() || !FLAG_log) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001354 StringBuilder s(parameter.length() + 1);
1355 for (int i = 0; i < parameter.length(); ++i) {
1356 s.AddCharacter(static_cast<char>(parameter[i]));
1357 }
1358 char* parameter_string = s.Finalize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001359 Log::MessageBuilder msg(log_);
1360 msg.Append("debug-queue-event,%s,%15.3f,%s", event_type,
1361 base::OS::TimeCurrentMillis(), parameter_string);
Steve Blocka7e24c12009-10-30 11:49:00 +00001362 DeleteArray(parameter_string);
1363 msg.WriteToLogFile();
Steve Blocka7e24c12009-10-30 11:49:00 +00001364}
1365
Ben Murdoch61f157c2016-09-16 13:49:30 +01001366void Logger::RuntimeCallTimerEvent() {
1367 RuntimeCallStats* stats = isolate_->counters()->runtime_call_stats();
1368 RuntimeCallTimer* timer = stats->current_timer();
1369 if (timer == nullptr) return;
1370 RuntimeCallCounter* counter = timer->counter();
1371 if (counter == nullptr) return;
1372 Log::MessageBuilder msg(log_);
1373 msg.Append("active-runtime-timer,");
1374 msg.AppendDoubleQuotedString(counter->name);
1375 msg.WriteToLogFile();
1376}
Steve Blocka7e24c12009-10-30 11:49:00 +00001377
Steve Blocka7e24c12009-10-30 11:49:00 +00001378void Logger::TickEvent(TickSample* sample, bool overflow) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001379 if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001380 if (FLAG_runtime_call_stats) {
1381 RuntimeCallTimerEvent();
1382 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001383 Log::MessageBuilder msg(log_);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001384 msg.Append("%s,", kLogEventsNames[CodeEventListener::TICK_EVENT]);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001385 msg.AppendAddress(sample->pc);
Ben Murdochc5610432016-08-08 18:44:38 +01001386 msg.Append(",%d", static_cast<int>(timer_.Elapsed().InMicroseconds()));
Steve Block44f0eee2011-05-26 01:26:41 +01001387 if (sample->has_external_callback) {
1388 msg.Append(",1,");
Ben Murdoch097c5b22016-05-18 11:27:45 +01001389 msg.AppendAddress(sample->external_callback_entry);
Steve Block44f0eee2011-05-26 01:26:41 +01001390 } else {
1391 msg.Append(",0,");
1392 msg.AppendAddress(sample->tos);
1393 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001394 msg.Append(",%d", static_cast<int>(sample->state));
1395 if (overflow) {
1396 msg.Append(",overflow");
1397 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001398 for (unsigned i = 0; i < sample->frames_count; ++i) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001399 msg.Append(',');
Ben Murdochb0fe1622011-05-05 13:52:32 +01001400 msg.AppendAddress(sample->stack[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001401 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001402 msg.WriteToLogFile();
1403}
1404
1405
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001406void Logger::StopProfiler() {
Steve Block44f0eee2011-05-26 01:26:41 +01001407 if (!log_->IsEnabled()) return;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001408 if (profiler_ != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001409 profiler_->pause();
1410 is_logging_ = false;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001411 removeCodeEventListener(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001412 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001413}
1414
1415
1416// This function can be called when Log's mutex is acquired,
1417// either from main or Profiler's thread.
Steve Block44f0eee2011-05-26 01:26:41 +01001418void Logger::LogFailure() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001419 StopProfiler();
Steve Blocka7e24c12009-10-30 11:49:00 +00001420}
1421
1422
Ben Murdochb0fe1622011-05-05 13:52:32 +01001423class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor {
1424 public:
1425 EnumerateOptimizedFunctionsVisitor(Handle<SharedFunctionInfo>* sfis,
Ben Murdochda12d292016-06-02 14:46:10 +01001426 Handle<AbstractCode>* code_objects,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001427 int* count)
Ben Murdochda12d292016-06-02 14:46:10 +01001428 : sfis_(sfis), code_objects_(code_objects), count_(count) {}
Ben Murdochb0fe1622011-05-05 13:52:32 +01001429
1430 virtual void EnterContext(Context* context) {}
1431 virtual void LeaveContext(Context* context) {}
1432
1433 virtual void VisitFunction(JSFunction* function) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001434 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(function->shared());
1435 Object* maybe_script = sfi->script();
1436 if (maybe_script->IsScript()
1437 && !Script::cast(maybe_script)->HasValidSource()) return;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001438 if (sfis_ != NULL) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001439 sfis_[*count_] = Handle<SharedFunctionInfo>(sfi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001440 }
1441 if (code_objects_ != NULL) {
Ben Murdochda12d292016-06-02 14:46:10 +01001442 DCHECK(function->abstract_code()->kind() ==
1443 AbstractCode::OPTIMIZED_FUNCTION);
1444 code_objects_[*count_] = Handle<AbstractCode>(function->abstract_code());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001445 }
1446 *count_ = *count_ + 1;
1447 }
1448
1449 private:
1450 Handle<SharedFunctionInfo>* sfis_;
Ben Murdochda12d292016-06-02 14:46:10 +01001451 Handle<AbstractCode>* code_objects_;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001452 int* count_;
1453};
1454
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001455static int EnumerateCompiledFunctions(Heap* heap,
1456 Handle<SharedFunctionInfo>* sfis,
Ben Murdochda12d292016-06-02 14:46:10 +01001457 Handle<AbstractCode>* code_objects) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001458 HeapIterator iterator(heap);
1459 DisallowHeapAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +00001460 int compiled_funcs_count = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001461
1462 // Iterate the heap to find shared function info objects and record
1463 // the unoptimized code for them.
Leon Clarked91b9f72010-01-27 17:25:45 +00001464 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001465 if (!obj->IsSharedFunctionInfo()) continue;
1466 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
1467 if (sfi->is_compiled()
1468 && (!sfi->script()->IsScript()
1469 || Script::cast(sfi->script())->HasValidSource())) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001470 if (sfis != NULL) {
Steve Block3ce2e202009-11-05 08:53:23 +00001471 sfis[compiled_funcs_count] = Handle<SharedFunctionInfo>(sfi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001472 }
1473 if (code_objects != NULL) {
Ben Murdochda12d292016-06-02 14:46:10 +01001474 code_objects[compiled_funcs_count] =
1475 Handle<AbstractCode>(sfi->abstract_code());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001476 }
Steve Block3ce2e202009-11-05 08:53:23 +00001477 ++compiled_funcs_count;
Steve Blocka7e24c12009-10-30 11:49:00 +00001478 }
1479 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001480
1481 // Iterate all optimized functions in all contexts.
1482 EnumerateOptimizedFunctionsVisitor visitor(sfis,
1483 code_objects,
1484 &compiled_funcs_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001485 Deoptimizer::VisitAllOptimizedFunctions(heap->isolate(), &visitor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001486
Steve Block3ce2e202009-11-05 08:53:23 +00001487 return compiled_funcs_count;
1488}
1489
1490
Steve Blockd0582a62009-12-15 09:54:21 +00001491void Logger::LogCodeObject(Object* object) {
Ben Murdochda12d292016-06-02 14:46:10 +01001492 AbstractCode* code_object = AbstractCode::cast(object);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001493 CodeEventListener::LogEventsAndTags tag = CodeEventListener::STUB_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001494 const char* description = "Unknown code from the snapshot";
1495 switch (code_object->kind()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001496 case AbstractCode::FUNCTION:
1497 case AbstractCode::INTERPRETED_FUNCTION:
1498 case AbstractCode::OPTIMIZED_FUNCTION:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001499 return; // We log this later using LogCompiledFunctions.
Ben Murdochda12d292016-06-02 14:46:10 +01001500 case AbstractCode::BYTECODE_HANDLER:
1501 return; // We log it later by walking the dispatch table.
1502 case AbstractCode::BINARY_OP_IC: // fall through
1503 case AbstractCode::COMPARE_IC: // fall through
1504 case AbstractCode::TO_BOOLEAN_IC: // fall through
1505
1506 case AbstractCode::STUB:
1507 description =
1508 CodeStub::MajorName(CodeStub::GetMajorKey(code_object->GetCode()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001509 if (description == NULL)
1510 description = "A stub from the snapshot";
Ben Murdoch61f157c2016-09-16 13:49:30 +01001511 tag = CodeEventListener::STUB_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001512 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001513 case AbstractCode::REGEXP:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001514 description = "Regular expression code";
Ben Murdoch61f157c2016-09-16 13:49:30 +01001515 tag = CodeEventListener::REG_EXP_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001516 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001517 case AbstractCode::BUILTIN:
1518 description =
1519 isolate_->builtins()->name(code_object->GetCode()->builtin_index());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001520 tag = CodeEventListener::BUILTIN_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001521 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001522 case AbstractCode::HANDLER:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001523 description = "An IC handler from the snapshot";
Ben Murdoch61f157c2016-09-16 13:49:30 +01001524 tag = CodeEventListener::HANDLER_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001525 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001526 case AbstractCode::KEYED_LOAD_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001527 description = "A keyed load IC from the snapshot";
Ben Murdoch61f157c2016-09-16 13:49:30 +01001528 tag = CodeEventListener::KEYED_LOAD_IC_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001529 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001530 case AbstractCode::LOAD_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001531 description = "A load IC from the snapshot";
Ben Murdoch61f157c2016-09-16 13:49:30 +01001532 tag = CodeEventListener::LOAD_IC_TAG;
1533 break;
1534 case AbstractCode::LOAD_GLOBAL_IC:
1535 description = "A load global IC from the snapshot";
1536 tag = Logger::LOAD_GLOBAL_IC_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001537 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001538 case AbstractCode::CALL_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001539 description = "A call IC from the snapshot";
Ben Murdoch61f157c2016-09-16 13:49:30 +01001540 tag = CodeEventListener::CALL_IC_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001541 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001542 case AbstractCode::STORE_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001543 description = "A store IC from the snapshot";
Ben Murdoch61f157c2016-09-16 13:49:30 +01001544 tag = CodeEventListener::STORE_IC_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001545 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001546 case AbstractCode::KEYED_STORE_IC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001547 description = "A keyed store IC from the snapshot";
Ben Murdoch61f157c2016-09-16 13:49:30 +01001548 tag = CodeEventListener::KEYED_STORE_IC_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001549 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001550 case AbstractCode::WASM_FUNCTION:
1551 description = "A Wasm function";
Ben Murdoch61f157c2016-09-16 13:49:30 +01001552 tag = CodeEventListener::STUB_TAG;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001553 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001554 case AbstractCode::JS_TO_WASM_FUNCTION:
1555 description = "A JavaScript to Wasm adapter";
Ben Murdoch61f157c2016-09-16 13:49:30 +01001556 tag = CodeEventListener::STUB_TAG;
Ben Murdochda12d292016-06-02 14:46:10 +01001557 break;
1558 case AbstractCode::WASM_TO_JS_FUNCTION:
1559 description = "A Wasm to JavaScript adapter";
Ben Murdoch61f157c2016-09-16 13:49:30 +01001560 tag = CodeEventListener::STUB_TAG;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001561 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001562 case AbstractCode::NUMBER_OF_KINDS:
1563 UNIMPLEMENTED();
Steve Blockd0582a62009-12-15 09:54:21 +00001564 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001565 PROFILE(isolate_, CodeCreateEvent(tag, code_object, description));
Ben Murdochf87a2032010-10-22 12:50:53 +01001566}
1567
1568
Andrei Popescu31002712010-02-23 13:46:05 +00001569void Logger::LogCodeObjects() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001570 Heap* heap = isolate_->heap();
1571 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001572 "Logger::LogCodeObjects");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001573 HeapIterator iterator(heap);
1574 DisallowHeapAllocation no_gc;
Andrei Popescu31002712010-02-23 13:46:05 +00001575 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1576 if (obj->IsCode()) LogCodeObject(obj);
Ben Murdochda12d292016-06-02 14:46:10 +01001577 if (obj->IsBytecodeArray()) LogCodeObject(obj);
Andrei Popescu31002712010-02-23 13:46:05 +00001578 }
1579}
1580
Ben Murdochda12d292016-06-02 14:46:10 +01001581void Logger::LogBytecodeHandlers() {
1582 if (!FLAG_ignition) return;
1583
Ben Murdochc5610432016-08-08 18:44:38 +01001584 const interpreter::OperandScale kOperandScales[] = {
1585#define VALUE(Name, _) interpreter::OperandScale::k##Name,
1586 OPERAND_SCALE_LIST(VALUE)
1587#undef VALUE
1588 };
1589
Ben Murdochda12d292016-06-02 14:46:10 +01001590 const int last_index = static_cast<int>(interpreter::Bytecode::kLast);
Ben Murdochc5610432016-08-08 18:44:38 +01001591 interpreter::Interpreter* interpreter = isolate_->interpreter();
1592 for (auto operand_scale : kOperandScales) {
Ben Murdochda12d292016-06-02 14:46:10 +01001593 for (int index = 0; index <= last_index; ++index) {
1594 interpreter::Bytecode bytecode = interpreter::Bytecodes::FromByte(index);
1595 if (interpreter::Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) {
1596 Code* code = interpreter->GetBytecodeHandler(bytecode, operand_scale);
1597 std::string bytecode_name =
1598 interpreter::Bytecodes::ToString(bytecode, operand_scale);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001599 PROFILE(isolate_, CodeCreateEvent(
1600 CodeEventListener::BYTECODE_HANDLER_TAG,
1601 AbstractCode::cast(code), bytecode_name.c_str()));
Ben Murdochda12d292016-06-02 14:46:10 +01001602 }
1603 }
1604 }
1605}
Andrei Popescu31002712010-02-23 13:46:05 +00001606
Ben Murdoch589d6972011-11-30 16:04:58 +00001607void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
Ben Murdochda12d292016-06-02 14:46:10 +01001608 Handle<AbstractCode> code) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001609 Handle<String> func_name(shared->DebugName());
1610 if (shared->script()->IsScript()) {
1611 Handle<Script> script(Script::cast(shared->script()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001612 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
1613 int column_num =
1614 Script::GetColumnNumber(script, shared->start_position()) + 1;
Ben Murdoch589d6972011-11-30 16:04:58 +00001615 if (script->name()->IsString()) {
1616 Handle<String> script_name(String::cast(script->name()));
Ben Murdoch589d6972011-11-30 16:04:58 +00001617 if (line_num > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001618 PROFILE(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +00001619 CodeCreateEvent(
Ben Murdoch61f157c2016-09-16 13:49:30 +01001620 Logger::ToNativeByScript(
1621 CodeEventListener::LAZY_COMPILE_TAG, *script),
Ben Murdochc5610432016-08-08 18:44:38 +01001622 *code, *shared, *script_name, line_num, column_num));
Ben Murdoch589d6972011-11-30 16:04:58 +00001623 } else {
1624 // Can't distinguish eval and script here, so always use Script.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001625 PROFILE(isolate_,
1626 CodeCreateEvent(Logger::ToNativeByScript(
1627 CodeEventListener::SCRIPT_TAG, *script),
1628 *code, *shared, *script_name));
Ben Murdoch589d6972011-11-30 16:04:58 +00001629 }
1630 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001631 PROFILE(isolate_,
Ben Murdoch61f157c2016-09-16 13:49:30 +01001632 CodeCreateEvent(Logger::ToNativeByScript(
1633 CodeEventListener::LAZY_COMPILE_TAG, *script),
1634 *code, *shared, isolate_->heap()->empty_string(),
1635 line_num, column_num));
Ben Murdoch589d6972011-11-30 16:04:58 +00001636 }
1637 } else if (shared->IsApiFunction()) {
1638 // API function.
1639 FunctionTemplateInfo* fun_data = shared->get_api_func_data();
1640 Object* raw_call_data = fun_data->call_code();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001641 if (!raw_call_data->IsUndefined(isolate_)) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001642 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1643 Object* callback_obj = call_data->callback();
1644 Address entry_point = v8::ToCData<Address>(callback_obj);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001645#if USES_FUNCTION_DESCRIPTORS
1646 entry_point = *FUNCTION_ENTRYPOINT_ADDRESS(entry_point);
1647#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001648 PROFILE(isolate_, CallbackEvent(*func_name, entry_point));
Ben Murdoch589d6972011-11-30 16:04:58 +00001649 }
1650 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001651 PROFILE(isolate_, CodeCreateEvent(CodeEventListener::LAZY_COMPILE_TAG,
1652 *code, *shared, *func_name));
Ben Murdoch589d6972011-11-30 16:04:58 +00001653 }
1654}
1655
1656
Steve Block3ce2e202009-11-05 08:53:23 +00001657void Logger::LogCompiledFunctions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001658 Heap* heap = isolate_->heap();
1659 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001660 "Logger::LogCompiledFunctions");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001661 HandleScope scope(isolate_);
1662 const int compiled_funcs_count = EnumerateCompiledFunctions(heap, NULL, NULL);
Kristian Monsen25f61362010-05-21 11:50:48 +01001663 ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
Ben Murdochda12d292016-06-02 14:46:10 +01001664 ScopedVector<Handle<AbstractCode> > code_objects(compiled_funcs_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001665 EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start());
Steve Blocka7e24c12009-10-30 11:49:00 +00001666
1667 // During iteration, there can be heap allocation due to
1668 // GetScriptLineNumber call.
1669 for (int i = 0; i < compiled_funcs_count; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001670 if (code_objects[i].is_identical_to(isolate_->builtins()->CompileLazy()))
Steve Block44f0eee2011-05-26 01:26:41 +01001671 continue;
Ben Murdoch589d6972011-11-30 16:04:58 +00001672 LogExistingFunction(sfis[i], code_objects[i]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001673 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001674}
1675
Steve Blockd0582a62009-12-15 09:54:21 +00001676
1677void Logger::LogAccessorCallbacks() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001678 Heap* heap = isolate_->heap();
1679 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001680 "Logger::LogAccessorCallbacks");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001681 HeapIterator iterator(heap);
1682 DisallowHeapAllocation no_gc;
Leon Clarked91b9f72010-01-27 17:25:45 +00001683 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001684 if (!obj->IsAccessorInfo()) continue;
1685 AccessorInfo* ai = AccessorInfo::cast(obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001686 if (!ai->name()->IsName()) continue;
Steve Blockd0582a62009-12-15 09:54:21 +00001687 Address getter_entry = v8::ToCData<Address>(ai->getter());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001688 Name* name = Name::cast(ai->name());
Steve Blockd0582a62009-12-15 09:54:21 +00001689 if (getter_entry != 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001690#if USES_FUNCTION_DESCRIPTORS
1691 getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(getter_entry);
1692#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001693 PROFILE(isolate_, GetterCallbackEvent(name, getter_entry));
Steve Blockd0582a62009-12-15 09:54:21 +00001694 }
1695 Address setter_entry = v8::ToCData<Address>(ai->setter());
1696 if (setter_entry != 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001697#if USES_FUNCTION_DESCRIPTORS
1698 setter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(setter_entry);
1699#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001700 PROFILE(isolate_, SetterCallbackEvent(name, setter_entry));
Steve Blockd0582a62009-12-15 09:54:21 +00001701 }
1702 }
1703}
1704
Steve Blocka7e24c12009-10-30 11:49:00 +00001705
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001706static void AddIsolateIdIfNeeded(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001707 Isolate* isolate) {
1708 if (FLAG_logfile_per_isolate) os << "isolate-" << isolate << "-";
1709}
1710
1711
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001712static void PrepareLogFileName(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001713 Isolate* isolate, const char* file_name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001714 int dir_separator_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001715 for (const char* p = file_name; *p; p++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001716 if (base::OS::isDirectorySeparator(*p)) dir_separator_count++;
1717 }
1718
1719 for (const char* p = file_name; *p; p++) {
1720 if (dir_separator_count == 0) {
1721 AddIsolateIdIfNeeded(os, isolate);
1722 dir_separator_count--;
1723 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001724 if (*p == '%') {
1725 p++;
1726 switch (*p) {
1727 case '\0':
1728 // If there's a % at the end of the string we back up
1729 // one character so we can escape the loop properly.
1730 p--;
1731 break;
1732 case 'p':
1733 os << base::OS::GetCurrentProcessId();
1734 break;
1735 case 't':
1736 // %t expands to the current time in milliseconds.
1737 os << static_cast<int64_t>(base::OS::TimeCurrentMillis());
1738 break;
1739 case '%':
1740 // %% expands (contracts really) to %.
1741 os << '%';
1742 break;
1743 default:
1744 // All other %'s expand to themselves.
1745 os << '%' << *p;
1746 break;
1747 }
1748 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001749 if (base::OS::isDirectorySeparator(*p)) dir_separator_count--;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001750 os << *p;
1751 }
1752 }
1753}
1754
1755
1756bool Logger::SetUp(Isolate* isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +01001757 // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
1758 if (is_initialized_) return true;
1759 is_initialized_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001760
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001761 std::ostringstream log_file_name;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001762 PrepareLogFileName(log_file_name, isolate, FLAG_logfile);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001763 log_->Initialize(log_file_name.str().c_str());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001764
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001765 if (FLAG_perf_basic_prof) {
1766 perf_basic_logger_ = new PerfBasicLogger();
1767 addCodeEventListener(perf_basic_logger_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001768 }
1769
Ben Murdochda12d292016-06-02 14:46:10 +01001770 if (FLAG_perf_prof) {
1771 perf_jit_logger_ = new PerfJitLogger();
1772 addCodeEventListener(perf_jit_logger_);
1773 }
1774
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001775 if (FLAG_ll_prof) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001776 ll_logger_ = new LowLevelLogger(log_file_name.str().c_str());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001777 addCodeEventListener(ll_logger_);
1778 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001779
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001780 ticker_ = new Ticker(isolate, kSamplingIntervalMs);
1781
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001782 if (Log::InitLogAtStart()) {
1783 is_logging_ = true;
Steve Block6ded16b2010-05-10 14:33:55 +01001784 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001785
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001786 if (FLAG_log_internal_timer_events || FLAG_prof_cpp) timer_.Start();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001787
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001788 if (FLAG_prof_cpp) {
Steve Block44f0eee2011-05-26 01:26:41 +01001789 profiler_ = new Profiler(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001790 is_logging_ = true;
1791 profiler_->Engage();
Steve Blocka7e24c12009-10-30 11:49:00 +00001792 }
1793
Ben Murdoch61f157c2016-09-16 13:49:30 +01001794 profiler_listener_.reset();
1795
1796 if (is_logging_) {
1797 addCodeEventListener(this);
1798 }
1799
Steve Blocka7e24c12009-10-30 11:49:00 +00001800 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001801}
1802
1803
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001804void Logger::SetCodeEventHandler(uint32_t options,
1805 JitCodeEventHandler event_handler) {
1806 if (jit_logger_) {
1807 removeCodeEventListener(jit_logger_);
1808 delete jit_logger_;
1809 jit_logger_ = NULL;
1810 }
1811
1812 if (event_handler) {
1813 jit_logger_ = new JitLogger(event_handler);
1814 addCodeEventListener(jit_logger_);
1815 if (options & kJitCodeEventEnumExisting) {
1816 HandleScope scope(isolate_);
1817 LogCodeObjects();
1818 LogCompiledFunctions();
1819 }
1820 }
1821}
1822
Ben Murdoch61f157c2016-09-16 13:49:30 +01001823void Logger::SetUpProfilerListener() {
1824 if (!is_initialized_) return;
1825 if (profiler_listener_.get() == nullptr) {
1826 profiler_listener_.reset(new ProfilerListener(isolate_));
1827 }
1828 addCodeEventListener(profiler_listener_.get());
1829}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001830
Ben Murdoch61f157c2016-09-16 13:49:30 +01001831void Logger::TearDownProfilerListener() {
1832 if (profiler_listener_->HasObservers()) return;
1833 removeCodeEventListener(profiler_listener_.get());
1834}
1835
1836sampler::Sampler* Logger::sampler() {
Steve Block44f0eee2011-05-26 01:26:41 +01001837 return ticker_;
1838}
1839
1840
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001841FILE* Logger::TearDown() {
1842 if (!is_initialized_) return NULL;
Steve Block44f0eee2011-05-26 01:26:41 +01001843 is_initialized_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001844
1845 // Stop the profiler before closing the file.
1846 if (profiler_ != NULL) {
1847 profiler_->Disengage();
1848 delete profiler_;
1849 profiler_ = NULL;
1850 }
1851
Steve Blocka7e24c12009-10-30 11:49:00 +00001852 delete ticker_;
1853 ticker_ = NULL;
1854
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001855 if (perf_basic_logger_) {
1856 removeCodeEventListener(perf_basic_logger_);
1857 delete perf_basic_logger_;
1858 perf_basic_logger_ = NULL;
1859 }
1860
Ben Murdochda12d292016-06-02 14:46:10 +01001861 if (perf_jit_logger_) {
1862 removeCodeEventListener(perf_jit_logger_);
1863 delete perf_jit_logger_;
1864 perf_jit_logger_ = NULL;
1865 }
1866
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001867 if (ll_logger_) {
1868 removeCodeEventListener(ll_logger_);
1869 delete ll_logger_;
1870 ll_logger_ = NULL;
1871 }
1872
1873 if (jit_logger_) {
1874 removeCodeEventListener(jit_logger_);
1875 delete jit_logger_;
1876 jit_logger_ = NULL;
1877 }
1878
Ben Murdoch61f157c2016-09-16 13:49:30 +01001879 if (profiler_listener_.get() != nullptr) {
1880 removeCodeEventListener(profiler_listener_.get());
1881 }
1882
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001883 return log_->Close();
Steve Blocka7e24c12009-10-30 11:49:00 +00001884}
1885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001886} // namespace internal
1887} // namespace v8