v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
log.cc
Go to the documentation of this file.
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <stdarg.h>
29 
30 #include "v8.h"
31 
32 #include "bootstrapper.h"
33 #include "code-stubs.h"
34 #include "cpu-profiler.h"
35 #include "deoptimizer.h"
36 #include "global-handles.h"
37 #include "log.h"
38 #include "log-utils.h"
39 #include "macro-assembler.h"
40 #include "platform.h"
41 #include "runtime-profiler.h"
42 #include "serialize.h"
43 #include "string-stream.h"
44 #include "vm-state-inl.h"
45 
46 namespace v8 {
47 namespace internal {
48 
49 
50 #define DECLARE_EVENT(ignore1, name) name,
51 static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
53 };
54 #undef DECLARE_EVENT
55 
56 
57 #define CALL_LISTENERS(Call) \
58 for (int i = 0; i < listeners_.length(); ++i) { \
59  listeners_[i]->Call; \
60 }
61 
62 #define PROFILER_LOG(Call) \
63  do { \
64  CpuProfiler* cpu_profiler = isolate_->cpu_profiler(); \
65  if (cpu_profiler->is_profiling()) { \
66  cpu_profiler->Call; \
67  } \
68  } while (false);
69 
70 // ComputeMarker must only be used when SharedFunctionInfo is known.
71 static const char* ComputeMarker(Code* code) {
72  switch (code->kind()) {
73  case Code::FUNCTION: return code->optimizable() ? "~" : "";
74  case Code::OPTIMIZED_FUNCTION: return "*";
75  default: return "";
76  }
77 }
78 
79 
81  public:
82  NameBuffer() { Reset(); }
83 
84  void Reset() {
85  utf8_pos_ = 0;
86  }
87 
89  Reset();
90  AppendBytes(kLogEventsNames[tag]);
91  AppendByte(':');
92  }
93 
94  void AppendName(Name* name) {
95  if (name->IsString()) {
97  } else {
98  Symbol* symbol = Symbol::cast(name);
99  AppendBytes("symbol(");
100  if (!symbol->name()->IsUndefined()) {
101  AppendBytes("\"");
102  AppendString(String::cast(symbol->name()));
103  AppendBytes("\" ");
104  }
105  AppendBytes("hash ");
106  AppendHex(symbol->Hash());
107  AppendByte(')');
108  }
109  }
110 
111  void AppendString(String* str) {
112  if (str == NULL) return;
113  int uc16_length = Min(str->length(), kUtf16BufferSize);
114  String::WriteToFlat(str, utf16_buffer, 0, uc16_length);
116  for (int i = 0; i < uc16_length && utf8_pos_ < kUtf8BufferSize; ++i) {
117  uc16 c = utf16_buffer[i];
119  utf8_buffer_[utf8_pos_++] = static_cast<char>(c);
120  } else {
121  int char_length = unibrow::Utf8::Length(c, previous);
122  if (utf8_pos_ + char_length > kUtf8BufferSize) break;
123  unibrow::Utf8::Encode(utf8_buffer_ + utf8_pos_, c, previous);
124  utf8_pos_ += char_length;
125  }
126  previous = c;
127  }
128  }
129 
130  void AppendBytes(const char* bytes, int size) {
131  size = Min(size, kUtf8BufferSize - utf8_pos_);
132  OS::MemCopy(utf8_buffer_ + utf8_pos_, bytes, size);
133  utf8_pos_ += size;
134  }
135 
136  void AppendBytes(const char* bytes) {
137  AppendBytes(bytes, StrLength(bytes));
138  }
139 
140  void AppendByte(char c) {
141  if (utf8_pos_ >= kUtf8BufferSize) return;
142  utf8_buffer_[utf8_pos_++] = c;
143  }
144 
145  void AppendInt(int n) {
146  Vector<char> buffer(utf8_buffer_ + utf8_pos_,
147  kUtf8BufferSize - utf8_pos_);
148  int size = OS::SNPrintF(buffer, "%d", n);
149  if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
150  utf8_pos_ += size;
151  }
152  }
153 
154  void AppendHex(uint32_t n) {
155  Vector<char> buffer(utf8_buffer_ + utf8_pos_,
156  kUtf8BufferSize - utf8_pos_);
157  int size = OS::SNPrintF(buffer, "%x", n);
158  if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
159  utf8_pos_ += size;
160  }
161  }
162 
163  const char* get() { return utf8_buffer_; }
164  int size() const { return utf8_pos_; }
165 
166  private:
167  static const int kUtf8BufferSize = 512;
168  static const int kUtf16BufferSize = 128;
169 
170  int utf8_pos_;
171  char utf8_buffer_[kUtf8BufferSize];
172  uc16 utf16_buffer[kUtf16BufferSize];
173 };
174 
175 
177 
178 CodeEventLogger::~CodeEventLogger() { delete name_buffer_; }
179 
180 
182  Code* code,
183  const char* comment) {
184  name_buffer_->Init(tag);
185  name_buffer_->AppendBytes(comment);
186  LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
187 }
188 
189 
191  Code* code,
192  Name* name) {
193  name_buffer_->Init(tag);
194  name_buffer_->AppendName(name);
195  LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
196 }
197 
198 
200  Code* code,
201  SharedFunctionInfo* shared,
203  Name* name) {
204  name_buffer_->Init(tag);
205  name_buffer_->AppendBytes(ComputeMarker(code));
206  name_buffer_->AppendName(name);
207  LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
208 }
209 
210 
212  Code* code,
213  SharedFunctionInfo* shared,
215  Name* source, int line, int column) {
216  name_buffer_->Init(tag);
217  name_buffer_->AppendBytes(ComputeMarker(code));
218  name_buffer_->AppendString(shared->DebugName());
219  name_buffer_->AppendByte(' ');
220  if (source->IsString()) {
221  name_buffer_->AppendString(String::cast(source));
222  } else {
223  name_buffer_->AppendBytes("symbol(hash ");
224  name_buffer_->AppendHex(Name::cast(source)->Hash());
225  name_buffer_->AppendByte(')');
226  }
227  name_buffer_->AppendByte(':');
228  name_buffer_->AppendInt(line);
229  LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
230 }
231 
232 
234  Code* code,
235  int args_count) {
236  name_buffer_->Init(tag);
237  name_buffer_->AppendInt(args_count);
238  LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
239 }
240 
241 
243  name_buffer_->Init(Logger::REG_EXP_TAG);
244  name_buffer_->AppendString(source);
245  LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
246 }
247 
248 
249 // Linux perf tool logging support
251  public:
252  PerfBasicLogger();
253  virtual ~PerfBasicLogger();
254 
255  virtual void CodeMoveEvent(Address from, Address to) { }
256  virtual void CodeDeleteEvent(Address from) { }
257 
258  private:
259  virtual void LogRecordedBuffer(Code* code,
260  SharedFunctionInfo* shared,
261  const char* name,
262  int length);
263 
264  // Extension added to V8 log file name to get the low-level log name.
265  static const char kFilenameFormatString[];
266  static const int kFilenameBufferPadding;
267 
268  // File buffer size of the low-level log. We don't use the default to
269  // minimize the associated overhead.
270  static const int kLogBufferSize = 2 * MB;
271 
272  FILE* perf_output_handle_;
273 };
274 
275 const char PerfBasicLogger::kFilenameFormatString[] = "/tmp/perf-%d.map";
276 // Extra space for the PID in the filename
277 const int PerfBasicLogger::kFilenameBufferPadding = 16;
278 
280  : perf_output_handle_(NULL) {
281  // Open the perf JIT dump file.
282  int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
283  ScopedVector<char> perf_dump_name(bufferSize);
284  int size = OS::SNPrintF(
285  perf_dump_name,
286  kFilenameFormatString,
288  CHECK_NE(size, -1);
289  perf_output_handle_ = OS::FOpen(perf_dump_name.start(), OS::LogFileOpenMode);
290  CHECK_NE(perf_output_handle_, NULL);
291  setvbuf(perf_output_handle_, NULL, _IOFBF, kLogBufferSize);
292 }
293 
294 
296  fclose(perf_output_handle_);
297  perf_output_handle_ = NULL;
298 }
299 
300 
301 void PerfBasicLogger::LogRecordedBuffer(Code* code,
303  const char* name,
304  int length) {
305  ASSERT(code->instruction_start() == code->address() + Code::kHeaderSize);
306 
307  OS::FPrint(perf_output_handle_, "%llx %x %.*s\n",
308  reinterpret_cast<uint64_t>(code->instruction_start()),
309  code->instruction_size(),
310  length, name);
311 }
312 
313 
314 // Linux perf tool logging support
316  public:
317  PerfJitLogger();
318  virtual ~PerfJitLogger();
319 
320  virtual void CodeMoveEvent(Address from, Address to) { }
321  virtual void CodeDeleteEvent(Address from) { }
322 
323  private:
324  virtual void LogRecordedBuffer(Code* code,
325  SharedFunctionInfo* shared,
326  const char* name,
327  int length);
328 
329  // Extension added to V8 log file name to get the low-level log name.
330  static const char kFilenameFormatString[];
331  static const int kFilenameBufferPadding;
332 
333  // File buffer size of the low-level log. We don't use the default to
334  // minimize the associated overhead.
335  static const int kLogBufferSize = 2 * MB;
336 
337  void LogWriteBytes(const char* bytes, int size);
338  void LogWriteHeader();
339 
340  static const uint32_t kJitHeaderMagic = 0x4F74496A;
341  static const uint32_t kJitHeaderVersion = 0x2;
342  static const uint32_t kElfMachIA32 = 3;
343  static const uint32_t kElfMachX64 = 62;
344  static const uint32_t kElfMachARM = 40;
345  static const uint32_t kElfMachMIPS = 10;
346 
347  struct jitheader {
348  uint32_t magic;
349  uint32_t version;
350  uint32_t total_size;
351  uint32_t elf_mach;
352  uint32_t pad1;
353  uint32_t pid;
354  uint64_t timestamp;
355  };
356 
357  enum jit_record_type {
358  JIT_CODE_LOAD = 0
359  // JIT_CODE_UNLOAD = 1,
360  // JIT_CODE_CLOSE = 2,
361  // JIT_CODE_DEBUG_INFO = 3,
362  // JIT_CODE_PAGE_MAP = 4,
363  // JIT_CODE_MAX = 5
364  };
365 
366  struct jr_code_load {
367  uint32_t id;
368  uint32_t total_size;
369  uint64_t timestamp;
370  uint64_t vma;
371  uint64_t code_addr;
372  uint32_t code_size;
373  uint32_t align;
374  };
375 
376  uint32_t GetElfMach() {
377 #if V8_TARGET_ARCH_IA32
378  return kElfMachIA32;
379 #elif V8_TARGET_ARCH_X64
380  return kElfMachX64;
381 #elif V8_TARGET_ARCH_ARM
382  return kElfMachARM;
383 #elif V8_TARGET_ARCH_MIPS
384  return kElfMachMIPS;
385 #else
386  UNIMPLEMENTED();
387  return 0;
388 #endif
389  }
390 
391  FILE* perf_output_handle_;
392 };
393 
394 const char PerfJitLogger::kFilenameFormatString[] = "/tmp/jit-%d.dump";
395 
396 // Extra padding for the PID in the filename
397 const int PerfJitLogger::kFilenameBufferPadding = 16;
398 
400  : perf_output_handle_(NULL) {
401  // Open the perf JIT dump file.
402  int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
403  ScopedVector<char> perf_dump_name(bufferSize);
404  int size = OS::SNPrintF(
405  perf_dump_name,
406  kFilenameFormatString,
408  CHECK_NE(size, -1);
409  perf_output_handle_ = OS::FOpen(perf_dump_name.start(), OS::LogFileOpenMode);
410  CHECK_NE(perf_output_handle_, NULL);
411  setvbuf(perf_output_handle_, NULL, _IOFBF, kLogBufferSize);
412 
413  LogWriteHeader();
414 }
415 
416 
418  fclose(perf_output_handle_);
419  perf_output_handle_ = NULL;
420 }
421 
422 
423 void PerfJitLogger::LogRecordedBuffer(Code* code,
425  const char* name,
426  int length) {
427  ASSERT(code->instruction_start() == code->address() + Code::kHeaderSize);
428  ASSERT(perf_output_handle_ != NULL);
429 
430  const char* code_name = name;
431  uint8_t* code_pointer = reinterpret_cast<uint8_t*>(code->instruction_start());
432  uint32_t code_size = code->instruction_size();
433 
434  static const char string_terminator[] = "\0";
435 
436  jr_code_load code_load;
437  code_load.id = JIT_CODE_LOAD;
438  code_load.total_size = sizeof(code_load) + length + 1 + code_size;
439  code_load.timestamp =
440  static_cast<uint64_t>(OS::TimeCurrentMillis() * 1000.0);
441  code_load.vma = 0x0; // Our addresses are absolute.
442  code_load.code_addr = reinterpret_cast<uint64_t>(code->instruction_start());
443  code_load.code_size = code_size;
444  code_load.align = 0;
445 
446  LogWriteBytes(reinterpret_cast<const char*>(&code_load), sizeof(code_load));
447  LogWriteBytes(code_name, length);
448  LogWriteBytes(string_terminator, 1);
449  LogWriteBytes(reinterpret_cast<const char*>(code_pointer), code_size);
450 }
451 
452 
453 void PerfJitLogger::LogWriteBytes(const char* bytes, int size) {
454  size_t rv = fwrite(bytes, 1, size, perf_output_handle_);
455  ASSERT(static_cast<size_t>(size) == rv);
456  USE(rv);
457 }
458 
459 
460 void PerfJitLogger::LogWriteHeader() {
461  ASSERT(perf_output_handle_ != NULL);
462  jitheader header;
463  header.magic = kJitHeaderMagic;
464  header.version = kJitHeaderVersion;
465  header.total_size = sizeof(jitheader);
466  header.pad1 = 0xdeadbeef;
467  header.elf_mach = GetElfMach();
468  header.pid = OS::GetCurrentProcessId();
469  header.timestamp = static_cast<uint64_t>(OS::TimeCurrentMillis() * 1000.0);
470  LogWriteBytes(reinterpret_cast<const char*>(&header), sizeof(header));
471 }
472 
473 
474 // Low-level logging support.
475 #define LL_LOG(Call) if (ll_logger_) ll_logger_->Call;
476 
478  public:
479  explicit LowLevelLogger(const char* file_name);
480  virtual ~LowLevelLogger();
481 
482  virtual void CodeMoveEvent(Address from, Address to);
483  virtual void CodeDeleteEvent(Address from);
484  virtual void SnapshotPositionEvent(Address addr, int pos);
485  virtual void CodeMovingGCEvent();
486 
487  private:
488  virtual void LogRecordedBuffer(Code* code,
489  SharedFunctionInfo* shared,
490  const char* name,
491  int length);
492 
493  // Low-level profiling event structures.
494  struct CodeCreateStruct {
495  static const char kTag = 'C';
496 
497  int32_t name_size;
498  Address code_address;
499  int32_t code_size;
500  };
501 
502 
503  struct CodeMoveStruct {
504  static const char kTag = 'M';
505 
506  Address from_address;
507  Address to_address;
508  };
509 
510 
511  struct CodeDeleteStruct {
512  static const char kTag = 'D';
513 
514  Address address;
515  };
516 
517 
518  struct SnapshotPositionStruct {
519  static const char kTag = 'P';
520 
521  Address address;
522  int32_t position;
523  };
524 
525 
526  static const char kCodeMovingGCTag = 'G';
527 
528 
529  // Extension added to V8 log file name to get the low-level log name.
530  static const char kLogExt[];
531 
532  // File buffer size of the low-level log. We don't use the default to
533  // minimize the associated overhead.
534  static const int kLogBufferSize = 2 * MB;
535 
536  void LogCodeInfo();
537  void LogWriteBytes(const char* bytes, int size);
538 
539  template <typename T>
540  void LogWriteStruct(const T& s) {
541  char tag = T::kTag;
542  LogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag));
543  LogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s));
544  }
545 
546  FILE* ll_output_handle_;
547 };
548 
549 const char LowLevelLogger::kLogExt[] = ".ll";
550 
552  : ll_output_handle_(NULL) {
553  // Open the low-level log file.
554  size_t len = strlen(name);
555  ScopedVector<char> ll_name(static_cast<int>(len + sizeof(kLogExt)));
556  OS::MemCopy(ll_name.start(), name, len);
557  OS::MemCopy(ll_name.start() + len, kLogExt, sizeof(kLogExt));
558  ll_output_handle_ = OS::FOpen(ll_name.start(), OS::LogFileOpenMode);
559  setvbuf(ll_output_handle_, NULL, _IOFBF, kLogBufferSize);
560 
561  LogCodeInfo();
562 }
563 
564 
566  fclose(ll_output_handle_);
567  ll_output_handle_ = NULL;
568 }
569 
570 
571 void LowLevelLogger::LogCodeInfo() {
572 #if V8_TARGET_ARCH_IA32
573  const char arch[] = "ia32";
574 #elif V8_TARGET_ARCH_X64
575  const char arch[] = "x64";
576 #elif V8_TARGET_ARCH_ARM
577  const char arch[] = "arm";
578 #elif V8_TARGET_ARCH_MIPS
579  const char arch[] = "mips";
580 #else
581  const char arch[] = "unknown";
582 #endif
583  LogWriteBytes(arch, sizeof(arch));
584 }
585 
586 
587 void LowLevelLogger::LogRecordedBuffer(Code* code,
588  SharedFunctionInfo*,
589  const char* name,
590  int length) {
591  CodeCreateStruct event;
592  event.name_size = length;
593  event.code_address = code->instruction_start();
594  ASSERT(event.code_address == code->address() + Code::kHeaderSize);
595  event.code_size = code->instruction_size();
596  LogWriteStruct(event);
597  LogWriteBytes(name, length);
598  LogWriteBytes(
599  reinterpret_cast<const char*>(code->instruction_start()),
600  code->instruction_size());
601 }
602 
603 
605  CodeMoveStruct event;
606  event.from_address = from + Code::kHeaderSize;
607  event.to_address = to + Code::kHeaderSize;
608  LogWriteStruct(event);
609 }
610 
611 
613  CodeDeleteStruct event;
614  event.address = from + Code::kHeaderSize;
615  LogWriteStruct(event);
616 }
617 
618 
620  SnapshotPositionStruct event;
621  event.address = addr + Code::kHeaderSize;
622  event.position = pos;
623  LogWriteStruct(event);
624 }
625 
626 
627 void LowLevelLogger::LogWriteBytes(const char* bytes, int size) {
628  size_t rv = fwrite(bytes, 1, size, ll_output_handle_);
629  ASSERT(static_cast<size_t>(size) == rv);
630  USE(rv);
631 }
632 
633 
635  const char tag = kCodeMovingGCTag;
636 
637  LogWriteBytes(&tag, sizeof(tag));
638 }
639 
640 
641 #define JIT_LOG(Call) if (jit_logger_) jit_logger_->Call;
642 
643 
644 class JitLogger : public CodeEventLogger {
645  public:
646  explicit JitLogger(JitCodeEventHandler code_event_handler);
647 
648  virtual void CodeMoveEvent(Address from, Address to);
649  virtual void CodeDeleteEvent(Address from);
650  virtual void AddCodeLinePosInfoEvent(
651  void* jit_handler_data,
652  int pc_offset,
653  int position,
654  JitCodeEvent::PositionType position_type);
655 
656  void* StartCodePosInfoEvent();
657  void EndCodePosInfoEvent(Code* code, void* jit_handler_data);
658 
659  private:
660  virtual void LogRecordedBuffer(Code* code,
661  SharedFunctionInfo* shared,
662  const char* name,
663  int length);
664 
665  JitCodeEventHandler code_event_handler_;
666 };
667 
668 
670  : code_event_handler_(code_event_handler) {
671 }
672 
673 
674 void JitLogger::LogRecordedBuffer(Code* code,
675  SharedFunctionInfo* shared,
676  const char* name,
677  int length) {
678  JitCodeEvent event;
679  memset(&event, 0, sizeof(event));
680  event.type = JitCodeEvent::CODE_ADDED;
681  event.code_start = code->instruction_start();
682  event.code_len = code->instruction_size();
683  Handle<Script> script_handle;
684  if (shared && shared->script()->IsScript()) {
685  script_handle = Handle<Script>(Script::cast(shared->script()));
686  }
687  event.script = ToApiHandle<v8::Script>(script_handle);
688  event.name.str = name;
689  event.name.len = length;
690  code_event_handler_(&event);
691 }
692 
693 
695  Code* from_code = Code::cast(HeapObject::FromAddress(from));
696 
697  JitCodeEvent event;
699  event.code_start = from_code->instruction_start();
700  event.code_len = from_code->instruction_size();
701 
702  // Calculate the header size.
703  const size_t header_size =
704  from_code->instruction_start() - reinterpret_cast<byte*>(from_code);
705 
706  // Calculate the new start address of the instructions.
707  event.new_code_start =
708  reinterpret_cast<byte*>(HeapObject::FromAddress(to)) + header_size;
709 
710  code_event_handler_(&event);
711 }
712 
713 
715  Code* from_code = Code::cast(HeapObject::FromAddress(from));
716 
717  JitCodeEvent event;
719  event.code_start = from_code->instruction_start();
720  event.code_len = from_code->instruction_size();
721 
722  code_event_handler_(&event);
723 }
724 
726  void* jit_handler_data,
727  int pc_offset,
728  int position,
729  JitCodeEvent::PositionType position_type) {
730  JitCodeEvent event;
731  memset(&event, 0, sizeof(event));
733  event.user_data = jit_handler_data;
734  event.line_info.offset = pc_offset;
735  event.line_info.pos = position;
736  event.line_info.position_type = position_type;
737 
738  code_event_handler_(&event);
739 }
740 
741 
743  JitCodeEvent event;
744  memset(&event, 0, sizeof(event));
746 
747  code_event_handler_(&event);
748  return event.user_data;
749 }
750 
751 
752 void JitLogger::EndCodePosInfoEvent(Code* code, void* jit_handler_data) {
753  JitCodeEvent event;
754  memset(&event, 0, sizeof(event));
756  event.code_start = code->instruction_start();
757  event.user_data = jit_handler_data;
758 
759  code_event_handler_(&event);
760 }
761 
762 
763 // The Profiler samples pc and sp values for the main thread.
764 // Each sample is appended to a circular buffer.
765 // An independent thread removes data and writes it to the log.
766 // This design minimizes the time spent in the sampler.
767 //
768 class Profiler: public Thread {
769  public:
770  explicit Profiler(Isolate* isolate);
771  void Engage();
772  void Disengage();
773 
774  // Inserts collected profiling data into buffer.
776  if (paused_)
777  return;
778 
779  if (Succ(head_) == tail_) {
780  overflow_ = true;
781  } else {
782  buffer_[head_] = *sample;
783  head_ = Succ(head_);
784  buffer_semaphore_.Signal(); // Tell we have an element.
785  }
786  }
787 
788  virtual void Run();
789 
790  // Pause and Resume TickSample data collection.
791  void pause() { paused_ = true; }
792  void resume() { paused_ = false; }
793 
794  private:
795  // Waits for a signal and removes profiling data.
796  bool Remove(TickSample* sample) {
797  buffer_semaphore_.Wait(); // Wait for an element.
798  *sample = buffer_[tail_];
799  bool result = overflow_;
800  tail_ = Succ(tail_);
801  overflow_ = false;
802  return result;
803  }
804 
805  // Returns the next index in the cyclic buffer.
806  int Succ(int index) { return (index + 1) % kBufferSize; }
807 
808  Isolate* isolate_;
809  // Cyclic buffer for communicating profiling samples
810  // between the signal handler and the worker thread.
811  static const int kBufferSize = 128;
812  TickSample buffer_[kBufferSize]; // Buffer storage.
813  int head_; // Index to the buffer head.
814  int tail_; // Index to the buffer tail.
815  bool overflow_; // Tell whether a buffer overflow has occurred.
816  // Sempahore used for buffer synchronization.
817  Semaphore buffer_semaphore_;
818 
819  // Tells whether profiler is engaged, that is, processing thread is stated.
820  bool engaged_;
821 
822  // Tells whether worker thread should continue running.
823  bool running_;
824 
825  // Tells whether we are currently recording tick samples.
826  bool paused_;
827 };
828 
829 
830 //
831 // Ticker used to provide ticks to the profiler and the sliding state
832 // window.
833 //
834 class Ticker: public Sampler {
835  public:
836  Ticker(Isolate* isolate, int interval):
837  Sampler(isolate, interval),
838  profiler_(NULL) {}
839 
840  ~Ticker() { if (IsActive()) Stop(); }
841 
842  virtual void Tick(TickSample* sample) {
843  if (profiler_) profiler_->Insert(sample);
844  }
845 
847  ASSERT(profiler_ == NULL);
848  profiler_ = profiler;
850  if (!IsActive()) Start();
851  }
852 
853  void ClearProfiler() {
854  profiler_ = NULL;
855  if (IsActive()) Stop();
857  }
858 
859  private:
860  Profiler* profiler_;
861 };
862 
863 
864 //
865 // Profiler implementation.
866 //
868  : Thread("v8:Profiler"),
869  isolate_(isolate),
870  head_(0),
871  tail_(0),
872  overflow_(false),
873  buffer_semaphore_(0),
874  engaged_(false),
875  running_(false),
876  paused_(false) {
877 }
878 
879 
881  if (engaged_) return;
882  engaged_ = true;
883 
885 
886  // Start thread processing the profiler buffer.
887  running_ = true;
888  Start();
889 
890  // Register to get ticks.
891  Logger* logger = isolate_->logger();
892  logger->ticker_->SetProfiler(this);
893 
894  logger->ProfilerBeginEvent();
895 }
896 
897 
899  if (!engaged_) return;
900 
901  // Stop receiving ticks.
902  isolate_->logger()->ticker_->ClearProfiler();
903 
904  // Terminate the worker thread by setting running_ to false,
905  // inserting a fake element in the queue and then wait for
906  // the thread to terminate.
907  running_ = false;
909  // Reset 'paused_' flag, otherwise semaphore may not be signalled.
910  resume();
911  Insert(&sample);
912  Join();
913 
914  LOG(isolate_, UncheckedStringEvent("profiler", "end"));
915 }
916 
917 
920  bool overflow = Remove(&sample);
921  while (running_) {
922  LOG(isolate_, TickEvent(&sample, overflow));
923  overflow = Remove(&sample);
924  }
925 }
926 
927 
928 //
929 // Logger class implementation.
930 //
931 
932 Logger::Logger(Isolate* isolate)
933  : isolate_(isolate),
934  ticker_(NULL),
935  profiler_(NULL),
936  log_events_(NULL),
937  is_logging_(false),
938  log_(new Log(this)),
939  perf_basic_logger_(NULL),
940  perf_jit_logger_(NULL),
941  ll_logger_(NULL),
942  jit_logger_(NULL),
943  listeners_(5),
944  is_initialized_(false) {
945 }
946 
947 
948 Logger::~Logger() {
949  delete log_;
950 }
951 
952 
954  ASSERT(!hasCodeEventListener(listener));
955  listeners_.Add(listener);
956 }
957 
958 
960  ASSERT(hasCodeEventListener(listener));
961  listeners_.RemoveElement(listener);
962 }
963 
964 
966  return listeners_.Contains(listener);
967 }
968 
969 
970 void Logger::ProfilerBeginEvent() {
971  if (!log_->IsEnabled()) return;
972  Log::MessageBuilder msg(log_);
973  msg.Append("profiler,\"begin\",%d\n", kSamplingIntervalMs);
974  msg.WriteToLogFile();
975 }
976 
977 
978 void Logger::StringEvent(const char* name, const char* value) {
979  if (FLAG_log) UncheckedStringEvent(name, value);
980 }
981 
982 
983 void Logger::UncheckedStringEvent(const char* name, const char* value) {
984  if (!log_->IsEnabled()) return;
985  Log::MessageBuilder msg(log_);
986  msg.Append("%s,\"%s\"\n", name, value);
987  msg.WriteToLogFile();
988 }
989 
990 
991 void Logger::IntEvent(const char* name, int value) {
992  if (FLAG_log) UncheckedIntEvent(name, value);
993 }
994 
995 
996 void Logger::IntPtrTEvent(const char* name, intptr_t value) {
997  if (FLAG_log) UncheckedIntPtrTEvent(name, value);
998 }
999 
1000 
1001 void Logger::UncheckedIntEvent(const char* name, int value) {
1002  if (!log_->IsEnabled()) return;
1003  Log::MessageBuilder msg(log_);
1004  msg.Append("%s,%d\n", name, value);
1005  msg.WriteToLogFile();
1006 }
1007 
1008 
1009 void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
1010  if (!log_->IsEnabled()) return;
1011  Log::MessageBuilder msg(log_);
1012  msg.Append("%s,%" V8_PTR_PREFIX "d\n", name, value);
1013  msg.WriteToLogFile();
1014 }
1015 
1016 
1017 void Logger::HandleEvent(const char* name, Object** location) {
1018  if (!log_->IsEnabled() || !FLAG_log_handles) return;
1019  Log::MessageBuilder msg(log_);
1020  msg.Append("%s,0x%" V8PRIxPTR "\n", name, location);
1021  msg.WriteToLogFile();
1022 }
1023 
1024 
1025 // ApiEvent is private so all the calls come from the Logger class. It is the
1026 // caller's responsibility to ensure that log is enabled and that
1027 // FLAG_log_api is true.
1028 void Logger::ApiEvent(const char* format, ...) {
1029  ASSERT(log_->IsEnabled() && FLAG_log_api);
1030  Log::MessageBuilder msg(log_);
1031  va_list ap;
1032  va_start(ap, format);
1033  msg.AppendVA(format, ap);
1034  va_end(ap);
1035  msg.WriteToLogFile();
1036 }
1037 
1038 
1040  if (!log_->IsEnabled() || !FLAG_log_api) return;
1041  if (key->IsString()) {
1044  ApiEvent("api,check-security,\"%s\"\n", str.get());
1045  } else if (key->IsSymbol()) {
1046  Symbol* symbol = Symbol::cast(key);
1047  if (symbol->name()->IsUndefined()) {
1048  ApiEvent("api,check-security,symbol(hash %x)\n",
1049  Symbol::cast(key)->Hash());
1050  } else {
1051  SmartArrayPointer<char> str = String::cast(symbol->name())->ToCString(
1053  ApiEvent("api,check-security,symbol(\"%s\" hash %x)\n",
1054  str.get(),
1055  Symbol::cast(key)->Hash());
1056  }
1057  } else if (key->IsUndefined()) {
1058  ApiEvent("api,check-security,undefined\n");
1059  } else {
1060  ApiEvent("api,check-security,['no-name']\n");
1061  }
1062 }
1063 
1064 
1065 void Logger::SharedLibraryEvent(const char* library_path,
1066  uintptr_t start,
1067  uintptr_t end) {
1068  if (!log_->IsEnabled() || !FLAG_prof) return;
1069  Log::MessageBuilder msg(log_);
1070  msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
1071  library_path,
1072  start,
1073  end);
1074  msg.WriteToLogFile();
1075 }
1076 
1077 
1078 void Logger::SharedLibraryEvent(const wchar_t* library_path,
1079  uintptr_t start,
1080  uintptr_t end) {
1081  if (!log_->IsEnabled() || !FLAG_prof) return;
1082  Log::MessageBuilder msg(log_);
1083  msg.Append("shared-library,\"%ls\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
1084  library_path,
1085  start,
1086  end);
1087  msg.WriteToLogFile();
1088 }
1089 
1090 
1092  if (!log_->IsEnabled()) return;
1093  ASSERT(FLAG_log_internal_timer_events);
1094  Log::MessageBuilder msg(log_);
1095  int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
1096  msg.Append("code-deopt,%ld,%d\n", since_epoch, code->CodeSize());
1097  msg.WriteToLogFile();
1098 }
1099 
1100 
1101 void Logger::TimerEvent(StartEnd se, const char* name) {
1102  if (!log_->IsEnabled()) return;
1103  ASSERT(FLAG_log_internal_timer_events);
1104  Log::MessageBuilder msg(log_);
1105  int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
1106  const char* format = (se == START) ? "timer-event-start,\"%s\",%ld\n"
1107  : "timer-event-end,\"%s\",%ld\n";
1108  msg.Append(format, name, since_epoch);
1109  msg.WriteToLogFile();
1110 }
1111 
1112 
1115  ASSERT(isolate->current_vm_state() == JS);
1116  isolate->set_current_vm_state(EXTERNAL);
1117 }
1118 
1119 
1122  ASSERT(isolate->current_vm_state() == EXTERNAL);
1123  isolate->set_current_vm_state(JS);
1124 }
1125 
1126 
1127 void Logger::LogInternalEvents(const char* name, int se) {
1128  Isolate* isolate = Isolate::Current();
1129  LOG(isolate, TimerEvent(static_cast<StartEnd>(se), name));
1130 }
1131 
1132 
1134  isolate_->event_logger()(name_, se);
1135 }
1136 
1137 
1139  "V8.RecompileSynchronous";
1141  "V8.RecompileConcurrent";
1143  "V8.CompileFullCode";
1144 const char* Logger::TimerEventScope::v8_execute = "V8.Execute";
1145 const char* Logger::TimerEventScope::v8_external = "V8.External";
1146 
1147 
1148 void Logger::LogRegExpSource(Handle<JSRegExp> regexp) {
1149  // Prints "/" + re.source + "/" +
1150  // (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
1151  Log::MessageBuilder msg(log_);
1152 
1153  Handle<Object> source = GetProperty(regexp, "source");
1154  if (!source->IsString()) {
1155  msg.Append("no source");
1156  return;
1157  }
1158 
1159  switch (regexp->TypeTag()) {
1160  case JSRegExp::ATOM:
1161  msg.Append('a');
1162  break;
1163  default:
1164  break;
1165  }
1166  msg.Append('/');
1167  msg.AppendDetailed(*Handle<String>::cast(source), false);
1168  msg.Append('/');
1169 
1170  // global flag
1171  Handle<Object> global = GetProperty(regexp, "global");
1172  if (global->IsTrue()) {
1173  msg.Append('g');
1174  }
1175  // ignorecase flag
1176  Handle<Object> ignorecase = GetProperty(regexp, "ignoreCase");
1177  if (ignorecase->IsTrue()) {
1178  msg.Append('i');
1179  }
1180  // multiline flag
1181  Handle<Object> multiline = GetProperty(regexp, "multiline");
1182  if (multiline->IsTrue()) {
1183  msg.Append('m');
1184  }
1185 
1186  msg.WriteToLogFile();
1187 }
1188 
1189 
1190 void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
1191  if (!log_->IsEnabled() || !FLAG_log_regexp) return;
1192  Log::MessageBuilder msg(log_);
1193  msg.Append("regexp-compile,");
1194  LogRegExpSource(regexp);
1195  msg.Append(in_cache ? ",hit\n" : ",miss\n");
1196  msg.WriteToLogFile();
1197 }
1198 
1199 
1201  Handle<JSArray> args) {
1202  if (!log_->IsEnabled() || !FLAG_log_runtime) return;
1203  Log::MessageBuilder msg(log_);
1204  for (int i = 0; i < format.length(); i++) {
1205  char c = format[i];
1206  if (c == '%' && i <= format.length() - 2) {
1207  i++;
1208  ASSERT('0' <= format[i] && format[i] <= '9');
1209  // No exception expected when getting an element from an array literal.
1211  Object::GetElementNoExceptionThrown(isolate_, args, format[i] - '0');
1212  i++;
1213  switch (format[i]) {
1214  case 's':
1215  msg.AppendDetailed(String::cast(*obj), false);
1216  break;
1217  case 'S':
1218  msg.AppendDetailed(String::cast(*obj), true);
1219  break;
1220  case 'r':
1221  Logger::LogRegExpSource(Handle<JSRegExp>::cast(obj));
1222  break;
1223  case 'x':
1224  msg.Append("0x%x", Smi::cast(*obj)->value());
1225  break;
1226  case 'i':
1227  msg.Append("%i", Smi::cast(*obj)->value());
1228  break;
1229  default:
1230  UNREACHABLE();
1231  }
1232  } else {
1233  msg.Append(c);
1234  }
1235  }
1236  msg.Append('\n');
1237  msg.WriteToLogFile();
1238 }
1239 
1240 
1241 void Logger::ApiIndexedSecurityCheck(uint32_t index) {
1242  if (!log_->IsEnabled() || !FLAG_log_api) return;
1243  ApiEvent("api,check-security,%u\n", index);
1244 }
1245 
1246 
1247 void Logger::ApiNamedPropertyAccess(const char* tag,
1248  JSObject* holder,
1249  Object* name) {
1250  ASSERT(name->IsName());
1251  if (!log_->IsEnabled() || !FLAG_log_api) return;
1252  String* class_name_obj = holder->class_name();
1253  SmartArrayPointer<char> class_name =
1255  if (name->IsString()) {
1256  SmartArrayPointer<char> property_name =
1258  ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, class_name.get(),
1259  property_name.get());
1260  } else {
1261  Symbol* symbol = Symbol::cast(name);
1262  uint32_t hash = symbol->Hash();
1263  if (symbol->name()->IsUndefined()) {
1264  ApiEvent("api,%s,\"%s\",symbol(hash %x)\n", tag, class_name.get(), hash);
1265  } else {
1266  SmartArrayPointer<char> str = String::cast(symbol->name())->ToCString(
1268  ApiEvent("api,%s,\"%s\",symbol(\"%s\" hash %x)\n",
1269  tag, class_name.get(), str.get(), hash);
1270  }
1271  }
1272 }
1273 
1275  JSObject* holder,
1276  uint32_t index) {
1277  if (!log_->IsEnabled() || !FLAG_log_api) return;
1278  String* class_name_obj = holder->class_name();
1279  SmartArrayPointer<char> class_name =
1281  ApiEvent("api,%s,\"%s\",%u\n", tag, class_name.get(), index);
1282 }
1283 
1284 
1285 void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
1286  if (!log_->IsEnabled() || !FLAG_log_api) return;
1287  String* class_name_obj = object->class_name();
1288  SmartArrayPointer<char> class_name =
1290  ApiEvent("api,%s,\"%s\"\n", tag, class_name.get());
1291 }
1292 
1293 
1294 void Logger::ApiEntryCall(const char* name) {
1295  if (!log_->IsEnabled() || !FLAG_log_api) return;
1296  ApiEvent("api,%s\n", name);
1297 }
1298 
1299 
1300 void Logger::NewEvent(const char* name, void* object, size_t size) {
1301  if (!log_->IsEnabled() || !FLAG_log) return;
1302  Log::MessageBuilder msg(log_);
1303  msg.Append("new,%s,0x%" V8PRIxPTR ",%u\n", name, object,
1304  static_cast<unsigned int>(size));
1305  msg.WriteToLogFile();
1306 }
1307 
1308 
1309 void Logger::DeleteEvent(const char* name, void* object) {
1310  if (!log_->IsEnabled() || !FLAG_log) return;
1311  Log::MessageBuilder msg(log_);
1312  msg.Append("delete,%s,0x%" V8PRIxPTR "\n", name, object);
1313  msg.WriteToLogFile();
1314 }
1315 
1316 
1317 void Logger::NewEventStatic(const char* name, void* object, size_t size) {
1318  Isolate::Current()->logger()->NewEvent(name, object, size);
1319 }
1320 
1321 
1322 void Logger::DeleteEventStatic(const char* name, void* object) {
1323  Isolate::Current()->logger()->DeleteEvent(name, object);
1324 }
1325 
1326 
1327 void Logger::CallbackEventInternal(const char* prefix, Name* name,
1328  Address entry_point) {
1329  if (!FLAG_log_code || !log_->IsEnabled()) return;
1330  Log::MessageBuilder msg(log_);
1331  msg.Append("%s,%s,-2,",
1332  kLogEventsNames[CODE_CREATION_EVENT],
1333  kLogEventsNames[CALLBACK_TAG]);
1334  msg.AppendAddress(entry_point);
1335  if (name->IsString()) {
1338  msg.Append(",1,\"%s%s\"", prefix, str.get());
1339  } else {
1340  Symbol* symbol = Symbol::cast(name);
1341  if (symbol->name()->IsUndefined()) {
1342  msg.Append(",1,symbol(hash %x)", prefix, symbol->Hash());
1343  } else {
1344  SmartArrayPointer<char> str = String::cast(symbol->name())->ToCString(
1346  msg.Append(",1,symbol(\"%s\" hash %x)", prefix, str.get(),
1347  symbol->Hash());
1348  }
1349  }
1350  msg.Append('\n');
1351  msg.WriteToLogFile();
1352 }
1353 
1354 
1355 void Logger::CallbackEvent(Name* name, Address entry_point) {
1356  PROFILER_LOG(CallbackEvent(name, entry_point));
1357  CallbackEventInternal("", name, entry_point);
1358 }
1359 
1360 
1361 void Logger::GetterCallbackEvent(Name* name, Address entry_point) {
1362  PROFILER_LOG(GetterCallbackEvent(name, entry_point));
1363  CallbackEventInternal("get ", name, entry_point);
1364 }
1365 
1366 
1367 void Logger::SetterCallbackEvent(Name* name, Address entry_point) {
1368  PROFILER_LOG(SetterCallbackEvent(name, entry_point));
1369  CallbackEventInternal("set ", name, entry_point);
1370 }
1371 
1372 
1373 static void AppendCodeCreateHeader(Log::MessageBuilder* msg,
1375  Code* code) {
1376  ASSERT(msg);
1377  msg->Append("%s,%s,%d,",
1378  kLogEventsNames[Logger::CODE_CREATION_EVENT],
1379  kLogEventsNames[tag],
1380  code->kind());
1381  msg->AppendAddress(code->address());
1382  msg->Append(",%d,", code->ExecutableSize());
1383 }
1384 
1385 
1387  Code* code,
1388  const char* comment) {
1389  PROFILER_LOG(CodeCreateEvent(tag, code, comment));
1390 
1391  if (!is_logging_code_events()) return;
1392  CALL_LISTENERS(CodeCreateEvent(tag, code, comment));
1393 
1394  if (!FLAG_log_code || !log_->IsEnabled()) return;
1395  Log::MessageBuilder msg(log_);
1396  AppendCodeCreateHeader(&msg, tag, code);
1397  msg.AppendDoubleQuotedString(comment);
1398  msg.Append('\n');
1399  msg.WriteToLogFile();
1400 }
1401 
1402 
1404  Code* code,
1405  Name* name) {
1406  PROFILER_LOG(CodeCreateEvent(tag, code, name));
1407 
1408  if (!is_logging_code_events()) return;
1409  CALL_LISTENERS(CodeCreateEvent(tag, code, name));
1410 
1411  if (!FLAG_log_code || !log_->IsEnabled()) return;
1412  Log::MessageBuilder msg(log_);
1413  AppendCodeCreateHeader(&msg, tag, code);
1414  if (name->IsString()) {
1415  msg.Append('"');
1416  msg.AppendDetailed(String::cast(name), false);
1417  msg.Append('"');
1418  } else {
1419  msg.AppendSymbolName(Symbol::cast(name));
1420  }
1421  msg.Append('\n');
1422  msg.WriteToLogFile();
1423 }
1424 
1425 
1427  Code* code,
1428  SharedFunctionInfo* shared,
1430  Name* name) {
1431  PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, name));
1432 
1433  if (!is_logging_code_events()) return;
1434  CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, name));
1435 
1436  if (!FLAG_log_code || !log_->IsEnabled()) return;
1437  if (code == isolate_->builtins()->builtin(Builtins::kCompileUnoptimized))
1438  return;
1439 
1440  Log::MessageBuilder msg(log_);
1441  AppendCodeCreateHeader(&msg, tag, code);
1442  if (name->IsString()) {
1445  msg.Append("\"%s\"", str.get());
1446  } else {
1447  msg.AppendSymbolName(Symbol::cast(name));
1448  }
1449  msg.Append(',');
1450  msg.AppendAddress(shared->address());
1451  msg.Append(",%s", ComputeMarker(code));
1452  msg.Append('\n');
1453  msg.WriteToLogFile();
1454 }
1455 
1456 
1457 // Although, it is possible to extract source and line from
1458 // the SharedFunctionInfo object, we left it to caller
1459 // to leave logging functions free from heap allocations.
1461  Code* code,
1462  SharedFunctionInfo* shared,
1464  Name* source, int line, int column) {
1465  PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, source, line, column));
1466 
1467  if (!is_logging_code_events()) return;
1468  CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, source, line,
1469  column));
1470 
1471  if (!FLAG_log_code || !log_->IsEnabled()) return;
1472  Log::MessageBuilder msg(log_);
1473  AppendCodeCreateHeader(&msg, tag, code);
1476  msg.Append("\"%s ", name.get());
1477  if (source->IsString()) {
1478  SmartArrayPointer<char> sourcestr =
1480  msg.Append("%s", sourcestr.get());
1481  } else {
1482  msg.AppendSymbolName(Symbol::cast(source));
1483  }
1484  msg.Append(":%d:%d\",", line, column);
1485  msg.AppendAddress(shared->address());
1486  msg.Append(",%s", ComputeMarker(code));
1487  msg.Append('\n');
1488  msg.WriteToLogFile();
1489 }
1490 
1491 
1493  Code* code,
1494  int args_count) {
1495  PROFILER_LOG(CodeCreateEvent(tag, code, args_count));
1496 
1497  if (!is_logging_code_events()) return;
1498  CALL_LISTENERS(CodeCreateEvent(tag, code, args_count));
1499 
1500  if (!FLAG_log_code || !log_->IsEnabled()) return;
1501  Log::MessageBuilder msg(log_);
1502  AppendCodeCreateHeader(&msg, tag, code);
1503  msg.Append("\"args_count: %d\"", args_count);
1504  msg.Append('\n');
1505  msg.WriteToLogFile();
1506 }
1507 
1508 
1511 
1512  if (!is_logging_code_events()) return;
1513  if (!log_->IsEnabled() || !FLAG_ll_prof) return;
1516 }
1517 
1518 
1520  PROFILER_LOG(RegExpCodeCreateEvent(code, source));
1521 
1522  if (!is_logging_code_events()) return;
1523  CALL_LISTENERS(RegExpCodeCreateEvent(code, source));
1524 
1525  if (!FLAG_log_code || !log_->IsEnabled()) return;
1526  Log::MessageBuilder msg(log_);
1527  AppendCodeCreateHeader(&msg, REG_EXP_TAG, code);
1528  msg.Append('"');
1529  msg.AppendDetailed(source, false);
1530  msg.Append('"');
1531  msg.Append('\n');
1532  msg.WriteToLogFile();
1533 }
1534 
1535 
1537  PROFILER_LOG(CodeMoveEvent(from, to));
1538 
1539  if (!is_logging_code_events()) return;
1540  CALL_LISTENERS(CodeMoveEvent(from, to));
1541  MoveEventInternal(CODE_MOVE_EVENT, from, to);
1542 }
1543 
1544 
1547 
1548  if (!is_logging_code_events()) return;
1550 
1551  if (!FLAG_log_code || !log_->IsEnabled()) return;
1552  Log::MessageBuilder msg(log_);
1553  msg.Append("%s,", kLogEventsNames[CODE_DELETE_EVENT]);
1554  msg.AppendAddress(from);
1555  msg.Append('\n');
1556  msg.WriteToLogFile();
1557 }
1558 
1559 
1560 void Logger::CodeLinePosInfoAddPositionEvent(void* jit_handler_data,
1561  int pc_offset,
1562  int position) {
1563  JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1564  pc_offset,
1565  position,
1567 }
1568 
1569 
1571  int pc_offset,
1572  int position) {
1573  JIT_LOG(AddCodeLinePosInfoEvent(jit_handler_data,
1574  pc_offset,
1575  position,
1577 }
1578 
1579 
1580 void Logger::CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder) {
1581  if (jit_logger_ != NULL) {
1582  pos_recorder->AttachJITHandlerData(jit_logger_->StartCodePosInfoEvent());
1583  }
1584 }
1585 
1586 
1588  void* jit_handler_data) {
1589  JIT_LOG(EndCodePosInfoEvent(code, jit_handler_data));
1590 }
1591 
1592 
1593 void Logger::CodeNameEvent(Address addr, int pos, const char* code_name) {
1594  if (code_name == NULL) return; // Not a code object.
1595  Log::MessageBuilder msg(log_);
1596  msg.Append("%s,%d,", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
1597  msg.AppendDoubleQuotedString(code_name);
1598  msg.Append("\n");
1599  msg.WriteToLogFile();
1600 }
1601 
1602 
1604  if (!log_->IsEnabled()) return;
1605  LL_LOG(SnapshotPositionEvent(addr, pos));
1606  if (!FLAG_log_snapshot_positions) return;
1607  Log::MessageBuilder msg(log_);
1608  msg.Append("%s,", kLogEventsNames[SNAPSHOT_POSITION_EVENT]);
1609  msg.AppendAddress(addr);
1610  msg.Append(",%d", pos);
1611  msg.Append('\n');
1612  msg.WriteToLogFile();
1613 }
1614 
1615 
1618 
1619  if (!is_logging_code_events()) return;
1620  MoveEventInternal(SHARED_FUNC_MOVE_EVENT, from, to);
1621 }
1622 
1623 
1624 void Logger::MoveEventInternal(LogEventsAndTags event,
1625  Address from,
1626  Address to) {
1627  if (!FLAG_log_code || !log_->IsEnabled()) return;
1628  Log::MessageBuilder msg(log_);
1629  msg.Append("%s,", kLogEventsNames[event]);
1630  msg.AppendAddress(from);
1631  msg.Append(',');
1632  msg.AppendAddress(to);
1633  msg.Append('\n');
1634  msg.WriteToLogFile();
1635 }
1636 
1637 
1638 void Logger::ResourceEvent(const char* name, const char* tag) {
1639  if (!log_->IsEnabled() || !FLAG_log) return;
1640  Log::MessageBuilder msg(log_);
1641  msg.Append("%s,%s,", name, tag);
1642 
1643  uint32_t sec, usec;
1644  if (OS::GetUserTime(&sec, &usec) != -1) {
1645  msg.Append("%d,%d,", sec, usec);
1646  }
1647  msg.Append("%.0f", OS::TimeCurrentMillis());
1648 
1649  msg.Append('\n');
1650  msg.WriteToLogFile();
1651 }
1652 
1653 
1655  if (!log_->IsEnabled() || !FLAG_log_suspect) return;
1656  Log::MessageBuilder msg(log_);
1657  String* class_name = obj->IsJSObject()
1658  ? JSObject::cast(obj)->class_name()
1659  : isolate_->heap()->empty_string();
1660  msg.Append("suspect-read,");
1661  msg.Append(class_name);
1662  msg.Append(',');
1663  if (name->IsString()) {
1664  msg.Append('"');
1665  msg.Append(String::cast(name));
1666  msg.Append('"');
1667  } else {
1668  msg.AppendSymbolName(Symbol::cast(name));
1669  }
1670  msg.Append('\n');
1671  msg.WriteToLogFile();
1672 }
1673 
1674 
1675 void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
1676  if (!log_->IsEnabled() || !FLAG_log_gc) return;
1677  Log::MessageBuilder msg(log_);
1678  // Using non-relative system time in order to be able to synchronize with
1679  // external memory profiling events (e.g. DOM memory size).
1680  msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f\n",
1681  space, kind, OS::TimeCurrentMillis());
1682  msg.WriteToLogFile();
1683 }
1684 
1685 
1686 void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
1687  if (!log_->IsEnabled() || !FLAG_log_gc) return;
1688  Log::MessageBuilder msg(log_);
1689  msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind);
1690  msg.WriteToLogFile();
1691 }
1692 
1693 
1694 void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
1695  if (!log_->IsEnabled() || !FLAG_log_gc) return;
1696  Log::MessageBuilder msg(log_);
1697  msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes);
1698  msg.WriteToLogFile();
1699 }
1700 
1701 
1702 void Logger::DebugTag(const char* call_site_tag) {
1703  if (!log_->IsEnabled() || !FLAG_log) return;
1704  Log::MessageBuilder msg(log_);
1705  msg.Append("debug-tag,%s\n", call_site_tag);
1706  msg.WriteToLogFile();
1707 }
1708 
1709 
1710 void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
1711  if (!log_->IsEnabled() || !FLAG_log) return;
1712  StringBuilder s(parameter.length() + 1);
1713  for (int i = 0; i < parameter.length(); ++i) {
1714  s.AddCharacter(static_cast<char>(parameter[i]));
1715  }
1716  char* parameter_string = s.Finalize();
1717  Log::MessageBuilder msg(log_);
1718  msg.Append("debug-queue-event,%s,%15.3f,%s\n",
1719  event_type,
1721  parameter_string);
1722  DeleteArray(parameter_string);
1723  msg.WriteToLogFile();
1724 }
1725 
1726 
1727 void Logger::TickEvent(TickSample* sample, bool overflow) {
1728  if (!log_->IsEnabled() || !FLAG_prof) return;
1729  Log::MessageBuilder msg(log_);
1730  msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
1731  msg.AppendAddress(sample->pc);
1732  msg.Append(",%ld", static_cast<int>(timer_.Elapsed().InMicroseconds()));
1733  if (sample->has_external_callback) {
1734  msg.Append(",1,");
1735  msg.AppendAddress(sample->external_callback);
1736  } else {
1737  msg.Append(",0,");
1738  msg.AppendAddress(sample->tos);
1739  }
1740  msg.Append(",%d", static_cast<int>(sample->state));
1741  if (overflow) {
1742  msg.Append(",overflow");
1743  }
1744  for (int i = 0; i < sample->frames_count; ++i) {
1745  msg.Append(',');
1746  msg.AppendAddress(sample->stack[i]);
1747  }
1748  msg.Append('\n');
1749  msg.WriteToLogFile();
1750 }
1751 
1752 
1754  if (!log_->IsEnabled()) return;
1755  if (profiler_ != NULL) {
1756  profiler_->pause();
1757  is_logging_ = false;
1758  }
1759 }
1760 
1761 
1762 // This function can be called when Log's mutex is acquired,
1763 // either from main or Profiler's thread.
1765  StopProfiler();
1766 }
1767 
1768 
1769 class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor {
1770  public:
1772  Handle<Code>* code_objects,
1773  int* count)
1774  : sfis_(sfis), code_objects_(code_objects), count_(count) { }
1775 
1776  virtual void EnterContext(Context* context) {}
1777  virtual void LeaveContext(Context* context) {}
1778 
1779  virtual void VisitFunction(JSFunction* function) {
1780  SharedFunctionInfo* sfi = SharedFunctionInfo::cast(function->shared());
1781  Object* maybe_script = sfi->script();
1782  if (maybe_script->IsScript()
1783  && !Script::cast(maybe_script)->HasValidSource()) return;
1784  if (sfis_ != NULL) {
1785  sfis_[*count_] = Handle<SharedFunctionInfo>(sfi);
1786  }
1787  if (code_objects_ != NULL) {
1788  ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
1789  code_objects_[*count_] = Handle<Code>(function->code());
1790  }
1791  *count_ = *count_ + 1;
1792  }
1793 
1794  private:
1796  Handle<Code>* code_objects_;
1797  int* count_;
1798 };
1799 
1800 
1801 static int EnumerateCompiledFunctions(Heap* heap,
1803  Handle<Code>* code_objects) {
1804  HeapIterator iterator(heap);
1805  DisallowHeapAllocation no_gc;
1806  int compiled_funcs_count = 0;
1807 
1808  // Iterate the heap to find shared function info objects and record
1809  // the unoptimized code for them.
1810  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1811  if (!obj->IsSharedFunctionInfo()) continue;
1812  SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
1813  if (sfi->is_compiled()
1814  && (!sfi->script()->IsScript()
1815  || Script::cast(sfi->script())->HasValidSource())) {
1816  if (sfis != NULL) {
1817  sfis[compiled_funcs_count] = Handle<SharedFunctionInfo>(sfi);
1818  }
1819  if (code_objects != NULL) {
1820  code_objects[compiled_funcs_count] = Handle<Code>(sfi->code());
1821  }
1822  ++compiled_funcs_count;
1823  }
1824  }
1825 
1826  // Iterate all optimized functions in all contexts.
1827  EnumerateOptimizedFunctionsVisitor visitor(sfis,
1828  code_objects,
1829  &compiled_funcs_count);
1830  Deoptimizer::VisitAllOptimizedFunctions(heap->isolate(), &visitor);
1831 
1832  return compiled_funcs_count;
1833 }
1834 
1835 
1836 void Logger::LogCodeObject(Object* object) {
1837  Code* code_object = Code::cast(object);
1838  LogEventsAndTags tag = Logger::STUB_TAG;
1839  const char* description = "Unknown code from the snapshot";
1840  switch (code_object->kind()) {
1841  case Code::FUNCTION:
1842  case Code::OPTIMIZED_FUNCTION:
1843  return; // We log this later using LogCompiledFunctions.
1844  case Code::BINARY_OP_IC:
1845  case Code::COMPARE_IC: // fall through
1846  case Code::COMPARE_NIL_IC: // fall through
1847  case Code::TO_BOOLEAN_IC: // fall through
1848  case Code::STUB:
1849  description =
1850  CodeStub::MajorName(CodeStub::GetMajorKey(code_object), true);
1851  if (description == NULL)
1852  description = "A stub from the snapshot";
1853  tag = Logger::STUB_TAG;
1854  break;
1855  case Code::REGEXP:
1856  description = "Regular expression code";
1857  tag = Logger::REG_EXP_TAG;
1858  break;
1859  case Code::BUILTIN:
1860  description = "A builtin from the snapshot";
1861  tag = Logger::BUILTIN_TAG;
1862  break;
1863  case Code::HANDLER:
1864  description = "An IC handler from the snapshot";
1865  tag = Logger::HANDLER_TAG;
1866  break;
1867  case Code::KEYED_LOAD_IC:
1868  description = "A keyed load IC from the snapshot";
1869  tag = Logger::KEYED_LOAD_IC_TAG;
1870  break;
1871  case Code::LOAD_IC:
1872  description = "A load IC from the snapshot";
1873  tag = Logger::LOAD_IC_TAG;
1874  break;
1875  case Code::STORE_IC:
1876  description = "A store IC from the snapshot";
1877  tag = Logger::STORE_IC_TAG;
1878  break;
1879  case Code::KEYED_STORE_IC:
1880  description = "A keyed store IC from the snapshot";
1881  tag = Logger::KEYED_STORE_IC_TAG;
1882  break;
1883  case Code::NUMBER_OF_KINDS:
1884  break;
1885  }
1886  PROFILE(isolate_, CodeCreateEvent(tag, code_object, description));
1887 }
1888 
1889 
1891  Heap* heap = isolate_->heap();
1893  "Logger::LogCodeObjects");
1894  HeapIterator iterator(heap);
1895  DisallowHeapAllocation no_gc;
1896  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1897  if (obj->IsCode()) LogCodeObject(obj);
1898  }
1899 }
1900 
1901 
1903  Handle<Code> code) {
1904  Handle<String> func_name(shared->DebugName());
1905  if (shared->script()->IsScript()) {
1906  Handle<Script> script(Script::cast(shared->script()));
1907  int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
1908  int column_num =
1909  GetScriptColumnNumber(script, shared->start_position()) + 1;
1910  if (script->name()->IsString()) {
1911  Handle<String> script_name(String::cast(script->name()));
1912  if (line_num > 0) {
1913  PROFILE(isolate_,
1915  Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
1916  *code, *shared, NULL,
1917  *script_name, line_num, column_num));
1918  } else {
1919  // Can't distinguish eval and script here, so always use Script.
1920  PROFILE(isolate_,
1922  Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
1923  *code, *shared, NULL, *script_name));
1924  }
1925  } else {
1926  PROFILE(isolate_,
1928  Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
1929  *code, *shared, NULL,
1930  isolate_->heap()->empty_string(), line_num, column_num));
1931  }
1932  } else if (shared->IsApiFunction()) {
1933  // API function.
1934  FunctionTemplateInfo* fun_data = shared->get_api_func_data();
1935  Object* raw_call_data = fun_data->call_code();
1936  if (!raw_call_data->IsUndefined()) {
1937  CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1938  Object* callback_obj = call_data->callback();
1939  Address entry_point = v8::ToCData<Address>(callback_obj);
1940  PROFILE(isolate_, CallbackEvent(*func_name, entry_point));
1941  }
1942  } else {
1943  PROFILE(isolate_,
1945  Logger::LAZY_COMPILE_TAG, *code, *shared, NULL, *func_name));
1946  }
1947 }
1948 
1949 
1951  Heap* heap = isolate_->heap();
1953  "Logger::LogCompiledFunctions");
1954  HandleScope scope(isolate_);
1955  const int compiled_funcs_count = EnumerateCompiledFunctions(heap, NULL, NULL);
1956  ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
1957  ScopedVector< Handle<Code> > code_objects(compiled_funcs_count);
1958  EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start());
1959 
1960  // During iteration, there can be heap allocation due to
1961  // GetScriptLineNumber call.
1962  for (int i = 0; i < compiled_funcs_count; ++i) {
1963  if (code_objects[i].is_identical_to(
1964  isolate_->builtins()->CompileUnoptimized()))
1965  continue;
1966  LogExistingFunction(sfis[i], code_objects[i]);
1967  }
1968 }
1969 
1970 
1972  Heap* heap = isolate_->heap();
1974  "Logger::LogAccessorCallbacks");
1975  HeapIterator iterator(heap);
1976  DisallowHeapAllocation no_gc;
1977  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1978  if (!obj->IsExecutableAccessorInfo()) continue;
1980  if (!ai->name()->IsName()) continue;
1981  Address getter_entry = v8::ToCData<Address>(ai->getter());
1982  Name* name = Name::cast(ai->name());
1983  if (getter_entry != 0) {
1984  PROFILE(isolate_, GetterCallbackEvent(name, getter_entry));
1985  }
1986  Address setter_entry = v8::ToCData<Address>(ai->setter());
1987  if (setter_entry != 0) {
1988  PROFILE(isolate_, SetterCallbackEvent(name, setter_entry));
1989  }
1990  }
1991 }
1992 
1993 
1994 static void AddIsolateIdIfNeeded(Isolate* isolate, StringStream* stream) {
1995  if (isolate->IsDefaultIsolate() || !FLAG_logfile_per_isolate) return;
1996  stream->Add("isolate-%p-", isolate);
1997 }
1998 
1999 
2000 static SmartArrayPointer<const char> PrepareLogFileName(
2001  Isolate* isolate, const char* file_name) {
2002  if (strchr(file_name, '%') != NULL || !isolate->IsDefaultIsolate()) {
2003  // If there's a '%' in the log file name we have to expand
2004  // placeholders.
2005  HeapStringAllocator allocator;
2006  StringStream stream(&allocator);
2007  AddIsolateIdIfNeeded(isolate, &stream);
2008  for (const char* p = file_name; *p; p++) {
2009  if (*p == '%') {
2010  p++;
2011  switch (*p) {
2012  case '\0':
2013  // If there's a % at the end of the string we back up
2014  // one character so we can escape the loop properly.
2015  p--;
2016  break;
2017  case 'p':
2018  stream.Add("%d", OS::GetCurrentProcessId());
2019  break;
2020  case 't': {
2021  // %t expands to the current time in milliseconds.
2022  double time = OS::TimeCurrentMillis();
2023  stream.Add("%.0f", FmtElm(time));
2024  break;
2025  }
2026  case '%':
2027  // %% expands (contracts really) to %.
2028  stream.Put('%');
2029  break;
2030  default:
2031  // All other %'s expand to themselves.
2032  stream.Put('%');
2033  stream.Put(*p);
2034  break;
2035  }
2036  } else {
2037  stream.Put(*p);
2038  }
2039  }
2040  return SmartArrayPointer<const char>(stream.ToCString());
2041  }
2042  int length = StrLength(file_name);
2043  char* str = NewArray<char>(length + 1);
2044  OS::MemCopy(str, file_name, length);
2045  str[length] = '\0';
2046  return SmartArrayPointer<const char>(str);
2047 }
2048 
2049 
2050 bool Logger::SetUp(Isolate* isolate) {
2051  // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
2052  if (is_initialized_) return true;
2053  is_initialized_ = true;
2054 
2055  // --ll-prof implies --log-code and --log-snapshot-positions.
2056  if (FLAG_ll_prof) {
2057  FLAG_log_snapshot_positions = true;
2058  }
2059 
2060  SmartArrayPointer<const char> log_file_name =
2061  PrepareLogFileName(isolate, FLAG_logfile);
2062  log_->Initialize(log_file_name.get());
2063 
2064 
2065  if (FLAG_perf_basic_prof) {
2066  perf_basic_logger_ = new PerfBasicLogger();
2067  addCodeEventListener(perf_basic_logger_);
2068  }
2069 
2070  if (FLAG_perf_jit_prof) {
2071  perf_jit_logger_ = new PerfJitLogger();
2072  addCodeEventListener(perf_jit_logger_);
2073  }
2074 
2075  if (FLAG_ll_prof) {
2076  ll_logger_ = new LowLevelLogger(log_file_name.get());
2077  addCodeEventListener(ll_logger_);
2078  }
2079 
2080  ticker_ = new Ticker(isolate, kSamplingIntervalMs);
2081 
2082  if (Log::InitLogAtStart()) {
2083  is_logging_ = true;
2084  }
2085 
2086  if (FLAG_prof) {
2087  profiler_ = new Profiler(isolate);
2088  is_logging_ = true;
2089  profiler_->Engage();
2090  }
2091 
2092  if (FLAG_log_internal_timer_events || FLAG_prof) timer_.Start();
2093 
2094  return true;
2095 }
2096 
2097 
2098 void Logger::SetCodeEventHandler(uint32_t options,
2099  JitCodeEventHandler event_handler) {
2100  if (jit_logger_) {
2101  removeCodeEventListener(jit_logger_);
2102  delete jit_logger_;
2103  jit_logger_ = NULL;
2104  }
2105 
2106  if (event_handler) {
2107  jit_logger_ = new JitLogger(event_handler);
2108  addCodeEventListener(jit_logger_);
2109  if (options & kJitCodeEventEnumExisting) {
2110  HandleScope scope(isolate_);
2111  LogCodeObjects();
2113  }
2114  }
2115 }
2116 
2117 
2119  return ticker_;
2120 }
2121 
2122 
2124  if (!is_initialized_) return NULL;
2125  is_initialized_ = false;
2126 
2127  // Stop the profiler before closing the file.
2128  if (profiler_ != NULL) {
2129  profiler_->Disengage();
2130  delete profiler_;
2131  profiler_ = NULL;
2132  }
2133 
2134  delete ticker_;
2135  ticker_ = NULL;
2136 
2137  if (perf_basic_logger_) {
2138  removeCodeEventListener(perf_basic_logger_);
2139  delete perf_basic_logger_;
2140  perf_basic_logger_ = NULL;
2141  }
2142 
2143  if (perf_jit_logger_) {
2144  removeCodeEventListener(perf_jit_logger_);
2145  delete perf_jit_logger_;
2146  perf_jit_logger_ = NULL;
2147  }
2148 
2149  if (ll_logger_) {
2150  removeCodeEventListener(ll_logger_);
2151  delete ll_logger_;
2152  ll_logger_ = NULL;
2153  }
2154 
2155  if (jit_logger_) {
2156  removeCodeEventListener(jit_logger_);
2157  delete jit_logger_;
2158  jit_logger_ = NULL;
2159  }
2160 
2161  return log_->Close();
2162 }
2163 
2164 } } // namespace v8::internal
byte * Address
Definition: globals.h:186
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
static void LogInternalEvents(const char *name, int se)
Definition: log.cc:1127
virtual void CodeMoveEvent(Address from, Address to)
Definition: log.cc:694
Code * builtin(Name name)
Definition: builtins.h:322
static void NewEventStatic(const char *name, void *object, size_t size)
Definition: log.cc:1317
void RegExpCodeCreateEvent(Code *code, String *source)
Definition: log.cc:1519
bool IsTrue() const
Definition: api.cc:2347
void EndCodePosInfoEvent(Code *code, void *jit_handler_data)
Definition: log.cc:752
static CallHandlerInfo * cast(Object *obj)
static const char * v8_recompile_concurrent
Definition: log.h:336
const char * ToCString(const v8::String::Utf8Value &value)
void CodeMoveEvent(Address from, Address to)
Definition: log.cc:1536
#define PROFILE(IsolateGetter, Call)
Definition: cpu-profiler.h:194
#define V8PRIxPTR
Definition: globals.h:228
virtual void VisitFunction(JSFunction *function)
Definition: log.cc:1779
#define CALL_LISTENERS(Call)
Definition: log.cc:57
void CollectAllGarbage(int flags, const char *gc_reason=NULL, const GCCallbackFlags gc_callback_flags=kNoGCCallbackFlags)
Definition: heap.cc:731
static void LogSharedLibraryAddresses(Isolate *isolate)
static ExecutableAccessorInfo * cast(Object *obj)
static String * cast(Object *obj)
static void EnterExternal(Isolate *isolate)
Definition: log.cc:1113
void CallbackEvent(Name *name, Address entry_point)
Definition: log.cc:1355
#define LOG(isolate, Call)
Definition: log.h:86
bool IsActive() const
Definition: sampler.h:106
static void DeleteEventStatic(const char *name, void *object)
Definition: log.cc:1322
static void SignalCodeMovingGC()
void GetterCallbackEvent(Name *name, Address entry_point)
Definition: log.cc:1361
virtual void CodeDeleteEvent(Address from)
Definition: log.cc:714
TickSample * sample
Address external_callback
Definition: sampler.h:68
void DecreaseProfilingDepth()
Definition: sampler.cc:686
kSerializedDataOffset Object
Definition: objects-inl.h:5016
Sampler * sampler()
Definition: log.cc:2118
virtual void Tick(TickSample *sample)
Definition: log.cc:842
bool is_logging_code_events()
Definition: log.h:358
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including on console Map counters to a file Enable debugger compile events enable GDBJIT enable GDBJIT interface for all code objects dump only objects containing this substring stress the GC compactor to flush out pretty print source code print source AST function name where to insert a breakpoint print scopes for builtins trace contexts operations print stuff during garbage collection report code statistics after GC report handles after GC trace cache state transitions print interface inference details prints when objects are turned into dictionaries report heap spill statistics along with trace isolate state changes trace regexp bytecode execution Minimal Log all events to the log file Log API events to the log file Log heap samples on garbage collection for the hp2ps tool log positions Log suspect operations Used with turns on browser compatible mode for profiling v8 Specify the name of the log file Enable low level linux profiler Enable perf linux profiler(experimental annotate support).") DEFINE_string(gc_fake_mmap
static int GetUserTime(uint32_t *secs, uint32_t *usecs)
Builtins * builtins()
Definition: isolate.h:948
int int32_t
Definition: unicode.cc:47
void LogCompiledFunctions()
Definition: log.cc:1950
void CodeDeleteEvent(Address from)
Definition: log.cc:1545
void CodeNameEvent(Address addr, int pos, const char *code_name)
Definition: log.cc:1593
static Handle< Object > GetElementNoExceptionThrown(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: objects-inl.h:1071
static bool InitLogAtStart()
Definition: log-utils.h:47
void SetProfiler(Profiler *profiler)
Definition: log.cc:846
void IntPtrTEvent(const char *name, intptr_t value)
Definition: log.cc:996
virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, Code *code, const char *comment)
Definition: log.cc:181
#define ASSERT(condition)
Definition: checks.h:329
int interval() const
Definition: sampler.h:88
static Script * cast(Object *obj)
virtual void CodeDeleteEvent(Address from)
Definition: log.cc:321
static SharedFunctionInfo * cast(Object *obj)
FILE * Close()
Definition: log-utils.cc:98
void ApiNamedSecurityCheck(Object *key)
Definition: log.cc:1039
int GetScriptColumnNumber(Handle< Script > script, int code_pos)
Definition: handles.cc:389
virtual ~PerfJitLogger()
Definition: log.cc:417
void ClearProfiler()
Definition: log.cc:853
void LogTimerEvent(StartEnd se)
Definition: log.cc:1133
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:196
virtual void CodeDeleteEvent(Address from)
Definition: log.cc:612
void HandleEvent(const char *name, Object **location)
Definition: log.cc:1017
void StopProfiler()
Definition: log.cc:1753
static Code * cast(Object *obj)
void Init(Logger::LogEventsAndTags tag)
Definition: log.cc:88
bool IsDefaultIsolate() const
Definition: isolate.h:501
static Symbol * cast(Object *obj)
static Smi * cast(Object *object)
void ApiIndexedSecurityCheck(uint32_t index)
Definition: log.cc:1241
void LogFailure()
Definition: log.cc:1764
void CodeStartLinePosInfoRecordEvent(PositionsRecorder *pos_recorder)
Definition: log.cc:1580
void SnapshotPositionEvent(Address addr, int pos)
Definition: log.cc:1603
void Add(Vector< const char > format, Vector< FmtElm > elms)
static void VisitAllOptimizedFunctions(Isolate *isolate, OptimizedFunctionVisitor *visitor)
Definition: deoptimizer.cc:312
void CodeDeoptEvent(Code *code)
Definition: log.cc:1091
#define PROFILER_LOG(Call)
Definition: log.cc:62
uint8_t byte
Definition: globals.h:185
SmartArrayPointer< char > ToCString(AllowNullsFlag allow_nulls, RobustnessFlag robustness_flag, int offset, int length, int *length_output=0)
Definition: objects.cc:8272
void HeapSampleBeginEvent(const char *space, const char *kind)
Definition: log.cc:1675
void CodeLinePosInfoAddPositionEvent(void *jit_handler_data, int pc_offset, int position)
Definition: log.cc:1560
virtual void CodeMoveEvent(Address from, Address to)
Definition: log.cc:255
static uchar Length(uchar chr, int previous)
Definition: unicode-inl.h:163
virtual void SnapshotPositionEvent(Address addr, int pos)
Definition: log.cc:619
#define UNREACHABLE()
Definition: checks.h:52
#define JIT_LOG(Call)
Definition: log.cc:641
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
Definition: flags.cc:211
T * start() const
Definition: utils.h:426
void addCodeEventListener(CodeEventListener *listener)
Definition: log.cc:953
LowLevelLogger(const char *file_name)
Definition: log.cc:551
void LogExistingFunction(Handle< SharedFunctionInfo > shared, Handle< Code > code)
Definition: log.cc:1902
static const char * v8_external
Definition: log.h:339
void Insert(TickSample *sample)
Definition: log.cc:775
void IncreaseProfilingDepth()
Definition: sampler.cc:678
static void MemCopy(void *dest, const void *src, size_t size)
Definition: platform.h:399
void CodeEndLinePosInfoRecordEvent(Code *code, void *jit_handler_data)
Definition: log.cc:1587
EventType type
Definition: v8.h:4538
byte * instruction_start()
Definition: objects-inl.h:5857
virtual void EnterContext(Context *context)
Definition: log.cc:1776
Profiler(Isolate *isolate)
Definition: log.cc:867
bool SetUp(Isolate *isolate)
Definition: log.cc:2050
static FILE * FOpen(const char *path, const char *mode)
void DebugEvent(const char *event_type, Vector< uint16_t > parameter)
Definition: log.cc:1710
virtual void CodeDeleteEvent(Address from)
Definition: log.cc:256
FILE * TearDown()
Definition: log.cc:2123
virtual void Run()
Definition: log.cc:918
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
void RegExpCompileEvent(Handle< JSRegExp > regexp, bool in_cache)
Definition: log.cc:1190
static int GetCurrentProcessId()
int length() const
Definition: utils.h:420
void * StartCodePosInfoEvent()
Definition: log.cc:742
bool IsEnabled()
Definition: log-utils.h:60
static double TimeCurrentMillis()
virtual void AddCodeLinePosInfoEvent(void *jit_handler_data, int pc_offset, int position, JitCodeEvent::PositionType position_type)
Definition: log.cc:725
static const int kMakeHeapIterableMask
Definition: heap.h:1264
#define V8_PTR_PREFIX
Definition: globals.h:220
Address stack[kMaxFramesCount]
Definition: sampler.h:71
void LogRuntime(Vector< const char > format, Handle< JSArray > args)
Definition: log.cc:1200
Ticker(Isolate *isolate, int interval)
Definition: log.cc:836
virtual void LeaveContext(Context *context)
Definition: log.cc:1777
virtual ~CodeEventLogger()
Definition: log.cc:178
void SuspectReadEvent(Name *name, Object *obj)
Definition: log.cc:1654
static unsigned Encode(char *out, uchar c, int previous, bool replace_invalid=false)
Definition: unicode-inl.h:114
V8_INLINE bool IsUndefined() const
Definition: v8.h:6229
void ApiNamedPropertyAccess(const char *tag, JSObject *holder, Object *name)
Definition: log.cc:1247
#define CHECK_NE(unexpected, value)
Definition: checks.h:256
int StrLength(const char *string)
Definition: utils.h:253
void LogCodeObjects()
Definition: log.cc:1890
#define T(name, string, precedence)
Definition: token.cc:48
void ApiIndexedPropertyAccess(const char *tag, JSObject *holder, uint32_t index)
Definition: log.cc:1274
void SharedLibraryEvent(const char *library_path, uintptr_t start, uintptr_t end)
Definition: log.cc:1065
static const char * v8_execute
Definition: log.h:338
V8_INLINE bool IsString() const
Definition: v8.h:6265
void ApiEntryCall(const char *name)
Definition: log.cc:1294
void(* JitCodeEventHandler)(const JitCodeEvent *event)
Definition: v8.h:4595
static int SNPrintF(Vector< char > str, const char *format,...)
bool hasCodeEventListener(CodeEventListener *listener)
Definition: log.cc:965
void HeapSampleEndEvent(const char *space, const char *kind)
Definition: log.cc:1686
void AppendBytes(const char *bytes)
Definition: log.cc:136
int GetScriptLineNumber(Handle< Script > script, int code_pos)
Definition: handles.cc:363
#define DECLARE_EVENT(ignore1, name)
Definition: log.cc:50
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
Definition: objects.cc:8635
EnumerateOptimizedFunctionsVisitor(Handle< SharedFunctionInfo > *sfis, Handle< Code > *code_objects, int *count)
Definition: log.cc:1771
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
Definition: flags.cc:317
void HeapSampleItemEvent(const char *type, int number, int bytes)
Definition: log.cc:1694
void DeleteEvent(const char *name, void *object)
Definition: log.cc:1309
#define UNIMPLEMENTED()
Definition: checks.h:50
uint16_t uc16
Definition: globals.h:309
int ExecutableSize()
Definition: objects.h:5499
virtual void RegExpCodeCreateEvent(Code *code, String *source)
Definition: log.cc:242
static const char * v8_recompile_synchronous
Definition: log.h:335
virtual ~PerfBasicLogger()
Definition: log.cc:295
void ApiObjectAccess(const char *tag, JSObject *obj)
Definition: log.cc:1285
static const int kHeaderSize
Definition: objects.h:5604
friend class Profiler
Definition: log.h:444
void CodeLinePosInfoAddStatementPositionEvent(void *jit_handler_data, int pc_offset, int position)
Definition: log.cc:1570
static void LeaveExternal(Isolate *isolate)
Definition: log.cc:1120
static const int kSamplingIntervalMs
Definition: log.h:384
void CodeMovingGCEvent()
Definition: log.cc:1509
JitLogger(JitCodeEventHandler code_event_handler)
Definition: log.cc:669
static const char * v8_compile_full_code
Definition: log.h:337
static HeapObject * FromAddress(Address address)
Definition: objects-inl.h:1369
void USE(T)
Definition: globals.h:341
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
Definition: assert-scope.h:214
static const unsigned kMaxOneByteChar
Definition: unicode.h:164
Logger * logger()
Definition: isolate.h:868
#define LL_LOG(Call)
Definition: log.cc:475
#define BUILTIN(name)
Definition: builtins.cc:143
void SharedFunctionInfoMoveEvent(Address from, Address to)
Definition: log.cc:1616
virtual void CodeMoveEvent(Address from, Address to)
Definition: log.cc:604
void IntEvent(const char *name, int value)
Definition: log.cc:991
void LogAccessorCallbacks()
Definition: log.cc:1971
HeapObject * obj
static Name * cast(Object *obj)
void Initialize(const char *log_file_name)
Definition: log-utils.cc:49
static void FPrint(FILE *out, const char *format,...)
void removeCodeEventListener(CodeEventListener *listener)
Definition: log.cc:959
SmartArrayPointer< const char > ToCString() const
virtual ~LowLevelLogger()
Definition: log.cc:565
void DeleteArray(T *array)
Definition: allocation.h:91
T Min(T a, T b)
Definition: utils.h:234
void AppendBytes(const char *bytes, int size)
Definition: log.cc:130
void CodeCreateEvent(LogEventsAndTags tag, Code *code, const char *source)
Definition: log.cc:1386
void DebugTag(const char *call_site_tag)
Definition: log.cc:1702
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
static const char *const LogFileOpenMode
Definition: platform.h:213
void ResourceEvent(const char *name, const char *tag)
Definition: log.cc:1638
static JSObject * cast(Object *obj)
void NewEvent(const char *name, void *object, size_t size)
Definition: log.cc:1300
virtual void CodeMovingGCEvent()
Definition: log.cc:634
static const int kNoPreviousCharacter
Definition: unicode.h:120
#define LOG_EVENTS_AND_TAGS_LIST(V)
Definition: log.h:103
void TimerEvent(StartEnd se, const char *name)
Definition: log.cc:1101
virtual void CodeMoveEvent(Address from, Address to)
Definition: log.cc:320
void StringEvent(const char *name, const char *value)
Definition: log.cc:978
void SetterCallbackEvent(Name *name, Address entry_point)
Definition: log.cc:1367
void SetCodeEventHandler(uint32_t options, JitCodeEventHandler event_handler)
Definition: log.cc:2098
const int MB
Definition: globals.h:246