v8  3.14.5(node0.10.28)
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 "deoptimizer.h"
35 #include "global-handles.h"
36 #include "log.h"
37 #include "macro-assembler.h"
38 #include "platform.h"
39 #include "runtime-profiler.h"
40 #include "serialize.h"
41 #include "string-stream.h"
42 #include "vm-state-inl.h"
43 
44 namespace v8 {
45 namespace internal {
46 
47 //
48 // Sliding state window. Updates counters to keep track of the last
49 // window of kBufferSize states. This is useful to track where we
50 // spent our time.
51 //
53  public:
54  explicit SlidingStateWindow(Isolate* isolate);
56  void AddState(StateTag state);
57 
58  private:
59  static const int kBufferSize = 256;
60  Counters* counters_;
61  int current_index_;
62  bool is_full_;
63  byte buffer_[kBufferSize];
64 
65 
66  void IncrementStateCounter(StateTag state) {
67  counters_->state_counters(state)->Increment();
68  }
69 
70 
71  void DecrementStateCounter(StateTag state) {
72  counters_->state_counters(state)->Decrement();
73  }
74 };
75 
76 
77 //
78 // The Profiler samples pc and sp values for the main thread.
79 // Each sample is appended to a circular buffer.
80 // An independent thread removes data and writes it to the log.
81 // This design minimizes the time spent in the sampler.
82 //
83 class Profiler: public Thread {
84  public:
85  explicit Profiler(Isolate* isolate);
86  void Engage();
87  void Disengage();
88 
89  // Inserts collected profiling data into buffer.
91  if (paused_)
92  return;
93 
94  if (Succ(head_) == tail_) {
95  overflow_ = true;
96  } else {
97  buffer_[head_] = *sample;
98  head_ = Succ(head_);
99  buffer_semaphore_->Signal(); // Tell we have an element.
100  }
101  }
102 
103  // Waits for a signal and removes profiling data.
105  buffer_semaphore_->Wait(); // Wait for an element.
106  *sample = buffer_[tail_];
107  bool result = overflow_;
108  tail_ = Succ(tail_);
109  overflow_ = false;
110  return result;
111  }
112 
113  void Run();
114 
115  // Pause and Resume TickSample data collection.
116  bool paused() const { return paused_; }
117  void pause() { paused_ = true; }
118  void resume() { paused_ = false; }
119 
120  private:
121  // Returns the next index in the cyclic buffer.
122  int Succ(int index) { return (index + 1) % kBufferSize; }
123 
124  Isolate* isolate_;
125  // Cyclic buffer for communicating profiling samples
126  // between the signal handler and the worker thread.
127  static const int kBufferSize = 128;
128  TickSample buffer_[kBufferSize]; // Buffer storage.
129  int head_; // Index to the buffer head.
130  int tail_; // Index to the buffer tail.
131  bool overflow_; // Tell whether a buffer overflow has occurred.
132  Semaphore* buffer_semaphore_; // Sempahore used for buffer synchronization.
133 
134  // Tells whether profiler is engaged, that is, processing thread is stated.
135  bool engaged_;
136 
137  // Tells whether worker thread should continue running.
138  bool running_;
139 
140  // Tells whether we are currently recording tick samples.
141  bool paused_;
142 };
143 
144 
145 //
146 // StackTracer implementation
147 //
149  ASSERT(isolate->IsInitialized());
150 
151  // Avoid collecting traces while doing GC.
152  if (sample->state == GC) return;
153 
154  const Address js_entry_sp =
156  if (js_entry_sp == 0) {
157  // Not executing JS now.
158  return;
159  }
160 
161  const Address callback = isolate->external_callback();
162  if (callback != NULL) {
163  sample->external_callback = callback;
164  sample->has_external_callback = true;
165  } else {
166  // Sample potential return address value for frameless invocation of
167  // stubs (we'll figure out later, if this value makes sense).
168  sample->tos = Memory::Address_at(sample->sp);
169  sample->has_external_callback = false;
170  }
171 
172  SafeStackTraceFrameIterator it(isolate,
173  sample->fp, sample->sp,
174  sample->sp, js_entry_sp);
175  int i = 0;
176  while (!it.done() && i < TickSample::kMaxFramesCount) {
177  sample->stack[i++] = it.frame()->pc();
178  it.Advance();
179  }
180  sample->frames_count = i;
181 }
182 
183 
184 //
185 // Ticker used to provide ticks to the profiler and the sliding state
186 // window.
187 //
188 class Ticker: public Sampler {
189  public:
190  Ticker(Isolate* isolate, int interval):
191  Sampler(isolate, interval),
192  window_(NULL),
193  profiler_(NULL) {}
194 
195  ~Ticker() { if (IsActive()) Stop(); }
196 
197  virtual void Tick(TickSample* sample) {
198  if (profiler_) profiler_->Insert(sample);
199  if (window_) window_->AddState(sample->state);
200  }
201 
203  window_ = window;
204  if (!IsActive()) Start();
205  }
206 
207  void ClearWindow() {
208  window_ = NULL;
209  if (!profiler_ && IsActive() && !RuntimeProfiler::IsEnabled()) Stop();
210  }
211 
212  void SetProfiler(Profiler* profiler) {
213  ASSERT(profiler_ == NULL);
214  profiler_ = profiler;
216  if (!FLAG_prof_lazy && !IsActive()) Start();
217  }
218 
219  void ClearProfiler() {
221  profiler_ = NULL;
222  if (!window_ && IsActive() && !RuntimeProfiler::IsEnabled()) Stop();
223  }
224 
225  protected:
226  virtual void DoSampleStack(TickSample* sample) {
227  StackTracer::Trace(isolate(), sample);
228  }
229 
230  private:
231  SlidingStateWindow* window_;
232  Profiler* profiler_;
233 };
234 
235 
236 //
237 // SlidingStateWindow implementation.
238 //
240  : counters_(isolate->counters()), current_index_(0), is_full_(false) {
241  for (int i = 0; i < kBufferSize; i++) {
242  buffer_[i] = static_cast<byte>(OTHER);
243  }
244  isolate->logger()->ticker_->SetWindow(this);
245 }
246 
247 
249  LOGGER->ticker_->ClearWindow();
250 }
251 
252 
254  if (is_full_) {
255  DecrementStateCounter(static_cast<StateTag>(buffer_[current_index_]));
256  } else if (current_index_ == kBufferSize - 1) {
257  is_full_ = true;
258  }
259  buffer_[current_index_] = static_cast<byte>(state);
260  IncrementStateCounter(state);
261  ASSERT(IsPowerOf2(kBufferSize));
262  current_index_ = (current_index_ + 1) & (kBufferSize - 1);
263 }
264 
265 
266 //
267 // Profiler implementation.
268 //
270  : Thread("v8:Profiler"),
271  isolate_(isolate),
272  head_(0),
273  tail_(0),
274  overflow_(false),
275  buffer_semaphore_(OS::CreateSemaphore(0)),
276  engaged_(false),
277  running_(false),
278  paused_(false) {
279 }
280 
281 
283  if (engaged_) return;
284  engaged_ = true;
285 
286  // TODO(mnaganov): This is actually "Chromium" mode. Flags need to be revised.
287  // http://code.google.com/p/v8/issues/detail?id=487
288  if (!FLAG_prof_lazy) {
290  }
291 
292  // Start thread processing the profiler buffer.
293  running_ = true;
294  Start();
295 
296  // Register to get ticks.
297  LOGGER->ticker_->SetProfiler(this);
298 
299  LOGGER->ProfilerBeginEvent();
300 }
301 
302 
304  if (!engaged_) return;
305 
306  // Stop receiving ticks.
307  LOGGER->ticker_->ClearProfiler();
308 
309  // Terminate the worker thread by setting running_ to false,
310  // inserting a fake element in the queue and then wait for
311  // the thread to terminate.
312  running_ = false;
314  // Reset 'paused_' flag, otherwise semaphore may not be signalled.
315  resume();
316  Insert(&sample);
317  Join();
318 
319  LOG(ISOLATE, UncheckedStringEvent("profiler", "end"));
320 }
321 
322 
325  bool overflow = Remove(&sample);
326  while (running_) {
327  LOG(isolate_, TickEvent(&sample, overflow));
328  overflow = Remove(&sample);
329  }
330 }
331 
332 
333 // Low-level profiling event structures.
334 
336  static const char kTag = 'C';
337 
341 };
342 
343 
345  static const char kTag = 'M';
346 
349 };
350 
351 
353  static const char kTag = 'D';
354 
356 };
357 
358 
360  static const char kTag = 'P';
361 
364 };
365 
366 
367 static const char kCodeMovingGCTag = 'G';
368 
369 
370 //
371 // Logger class implementation.
372 //
373 
375  public:
376  NameMap() : impl_(&PointerEquals) {}
377 
379  for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) {
380  DeleteArray(static_cast<const char*>(p->value));
381  }
382  }
383 
384  void Insert(Address code_address, const char* name, int name_size) {
385  HashMap::Entry* entry = FindOrCreateEntry(code_address);
386  if (entry->value == NULL) {
387  entry->value = CopyName(name, name_size);
388  }
389  }
390 
391  const char* Lookup(Address code_address) {
392  HashMap::Entry* entry = FindEntry(code_address);
393  return (entry != NULL) ? static_cast<const char*>(entry->value) : NULL;
394  }
395 
396  void Remove(Address code_address) {
397  HashMap::Entry* entry = FindEntry(code_address);
398  if (entry != NULL) {
399  DeleteArray(static_cast<char*>(entry->value));
400  RemoveEntry(entry);
401  }
402  }
403 
404  void Move(Address from, Address to) {
405  if (from == to) return;
406  HashMap::Entry* from_entry = FindEntry(from);
407  ASSERT(from_entry != NULL);
408  void* value = from_entry->value;
409  RemoveEntry(from_entry);
410  HashMap::Entry* to_entry = FindOrCreateEntry(to);
411  ASSERT(to_entry->value == NULL);
412  to_entry->value = value;
413  }
414 
415  private:
416  static bool PointerEquals(void* lhs, void* rhs) {
417  return lhs == rhs;
418  }
419 
420  static char* CopyName(const char* name, int name_size) {
421  char* result = NewArray<char>(name_size + 1);
422  for (int i = 0; i < name_size; ++i) {
423  char c = name[i];
424  if (c == '\0') c = ' ';
425  result[i] = c;
426  }
427  result[name_size] = '\0';
428  return result;
429  }
430 
431  HashMap::Entry* FindOrCreateEntry(Address code_address) {
432  return impl_.Lookup(code_address, ComputePointerHash(code_address), true);
433  }
434 
435  HashMap::Entry* FindEntry(Address code_address) {
436  return impl_.Lookup(code_address, ComputePointerHash(code_address), false);
437  }
438 
439  void RemoveEntry(HashMap::Entry* entry) {
440  impl_.Remove(entry->key, entry->hash);
441  }
442 
443  HashMap impl_;
444 
445  DISALLOW_COPY_AND_ASSIGN(NameMap);
446 };
447 
448 
450  public:
451  NameBuffer() { Reset(); }
452 
453  void Reset() {
454  utf8_pos_ = 0;
455  }
456 
457  void AppendString(String* str) {
458  if (str == NULL) return;
459  if (str->HasOnlyAsciiChars()) {
460  int utf8_length = Min(str->length(), kUtf8BufferSize - utf8_pos_);
461  String::WriteToFlat(str, utf8_buffer_ + utf8_pos_, 0, utf8_length);
462  utf8_pos_ += utf8_length;
463  return;
464  }
465  int uc16_length = Min(str->length(), kUtf16BufferSize);
466  String::WriteToFlat(str, utf16_buffer, 0, uc16_length);
468  for (int i = 0; i < uc16_length && utf8_pos_ < kUtf8BufferSize; ++i) {
469  uc16 c = utf16_buffer[i];
470  if (c <= String::kMaxAsciiCharCodeU) {
471  utf8_buffer_[utf8_pos_++] = static_cast<char>(c);
472  } else {
473  int char_length = unibrow::Utf8::Length(c, previous);
474  if (utf8_pos_ + char_length > kUtf8BufferSize) break;
475  unibrow::Utf8::Encode(utf8_buffer_ + utf8_pos_, c, previous);
476  utf8_pos_ += char_length;
477  }
478  previous = c;
479  }
480  }
481 
482  void AppendBytes(const char* bytes, int size) {
483  size = Min(size, kUtf8BufferSize - utf8_pos_);
484  memcpy(utf8_buffer_ + utf8_pos_, bytes, size);
485  utf8_pos_ += size;
486  }
487 
488  void AppendBytes(const char* bytes) {
489  AppendBytes(bytes, StrLength(bytes));
490  }
491 
492  void AppendByte(char c) {
493  if (utf8_pos_ >= kUtf8BufferSize) return;
494  utf8_buffer_[utf8_pos_++] = c;
495  }
496 
497  void AppendInt(int n) {
498  Vector<char> buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_);
499  int size = OS::SNPrintF(buffer, "%d", n);
500  if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
501  utf8_pos_ += size;
502  }
503  }
504 
505  const char* get() { return utf8_buffer_; }
506  int size() const { return utf8_pos_; }
507 
508  private:
509  static const int kUtf8BufferSize = 512;
510  static const int kUtf16BufferSize = 128;
511 
512  int utf8_pos_;
513  char utf8_buffer_[kUtf8BufferSize];
514  uc16 utf16_buffer[kUtf16BufferSize];
515 };
516 
517 
518 Logger::Logger()
519  : ticker_(NULL),
520  profiler_(NULL),
521  sliding_state_window_(NULL),
522  log_events_(NULL),
523  logging_nesting_(0),
524  cpu_profiler_nesting_(0),
525  log_(new Log(this)),
526  name_buffer_(new NameBuffer),
527  address_to_name_map_(NULL),
528  is_initialized_(false),
529  code_event_handler_(NULL),
530  last_address_(NULL),
531  prev_sp_(NULL),
532  prev_function_(NULL),
533  prev_to_(NULL),
534  prev_code_(NULL) {
535 }
536 
537 
538 Logger::~Logger() {
539  delete address_to_name_map_;
540  delete name_buffer_;
541  delete log_;
542 }
543 
544 
545 void Logger::IssueCodeAddedEvent(Code* code,
546  const char* name,
547  size_t name_len) {
548  JitCodeEvent event;
549  event.type = JitCodeEvent::CODE_ADDED;
550  event.code_start = code->instruction_start();
551  event.code_len = code->instruction_size();
552  event.name.str = name;
553  event.name.len = name_len;
554 
555  code_event_handler_(&event);
556 }
557 
558 
559 void Logger::IssueCodeMovedEvent(Address from, Address to) {
560  Code* from_code = Code::cast(HeapObject::FromAddress(from));
561 
562  JitCodeEvent event;
563  event.type = JitCodeEvent::CODE_MOVED;
564  event.code_start = from_code->instruction_start();
565  event.code_len = from_code->instruction_size();
566 
567  // Calculate the header size.
568  const size_t header_size =
569  from_code->instruction_start() - reinterpret_cast<byte*>(from_code);
570 
571  // Calculate the new start address of the instructions.
572  event.new_code_start =
573  reinterpret_cast<byte*>(HeapObject::FromAddress(to)) + header_size;
574 
575  code_event_handler_(&event);
576 }
577 
578 
579 void Logger::IssueCodeRemovedEvent(Address from) {
580  Code* from_code = Code::cast(HeapObject::FromAddress(from));
581 
582  JitCodeEvent event;
583  event.type = JitCodeEvent::CODE_REMOVED;
584  event.code_start = from_code->instruction_start();
585  event.code_len = from_code->instruction_size();
586 
587  code_event_handler_(&event);
588 }
589 
590 
591 #define DECLARE_EVENT(ignore1, name) name,
592 static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
594 };
595 #undef DECLARE_EVENT
596 
597 
598 void Logger::ProfilerBeginEvent() {
599  if (!log_->IsEnabled()) return;
600  LogMessageBuilder msg(this);
601  msg.Append("profiler,\"begin\",%d\n", kSamplingIntervalMs);
602  msg.WriteToLogFile();
603 }
604 
605 
606 void Logger::StringEvent(const char* name, const char* value) {
607  if (FLAG_log) UncheckedStringEvent(name, value);
608 }
609 
610 
611 void Logger::UncheckedStringEvent(const char* name, const char* value) {
612  if (!log_->IsEnabled()) return;
613  LogMessageBuilder msg(this);
614  msg.Append("%s,\"%s\"\n", name, value);
615  msg.WriteToLogFile();
616 }
617 
618 
619 void Logger::IntEvent(const char* name, int value) {
620  if (FLAG_log) UncheckedIntEvent(name, value);
621 }
622 
623 
624 void Logger::IntPtrTEvent(const char* name, intptr_t value) {
625  if (FLAG_log) UncheckedIntPtrTEvent(name, value);
626 }
627 
628 
629 void Logger::UncheckedIntEvent(const char* name, int value) {
630  if (!log_->IsEnabled()) return;
631  LogMessageBuilder msg(this);
632  msg.Append("%s,%d\n", name, value);
633  msg.WriteToLogFile();
634 }
635 
636 
637 void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
638  if (!log_->IsEnabled()) return;
639  LogMessageBuilder msg(this);
640  msg.Append("%s,%" V8_PTR_PREFIX "d\n", name, value);
641  msg.WriteToLogFile();
642 }
643 
644 
645 void Logger::HandleEvent(const char* name, Object** location) {
646  if (!log_->IsEnabled() || !FLAG_log_handles) return;
647  LogMessageBuilder msg(this);
648  msg.Append("%s,0x%" V8PRIxPTR "\n", name, location);
649  msg.WriteToLogFile();
650 }
651 
652 
653 // ApiEvent is private so all the calls come from the Logger class. It is the
654 // caller's responsibility to ensure that log is enabled and that
655 // FLAG_log_api is true.
656 void Logger::ApiEvent(const char* format, ...) {
657  ASSERT(log_->IsEnabled() && FLAG_log_api);
658  LogMessageBuilder msg(this);
659  va_list ap;
660  va_start(ap, format);
661  msg.AppendVA(format, ap);
662  va_end(ap);
663  msg.WriteToLogFile();
664 }
665 
666 
668  if (!log_->IsEnabled() || !FLAG_log_api) return;
669  if (key->IsString()) {
672  ApiEvent("api,check-security,\"%s\"\n", *str);
673  } else if (key->IsUndefined()) {
674  ApiEvent("api,check-security,undefined\n");
675  } else {
676  ApiEvent("api,check-security,['no-name']\n");
677  }
678 }
679 
680 
681 void Logger::SharedLibraryEvent(const char* library_path,
682  uintptr_t start,
683  uintptr_t end) {
684  if (!log_->IsEnabled() || !FLAG_prof) return;
685  LogMessageBuilder msg(this);
686  msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
687  library_path,
688  start,
689  end);
690  msg.WriteToLogFile();
691 }
692 
693 
694 void Logger::SharedLibraryEvent(const wchar_t* library_path,
695  uintptr_t start,
696  uintptr_t end) {
697  if (!log_->IsEnabled() || !FLAG_prof) return;
698  LogMessageBuilder msg(this);
699  msg.Append("shared-library,\"%ls\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR "\n",
700  library_path,
701  start,
702  end);
703  msg.WriteToLogFile();
704 }
705 
706 
707 void Logger::LogRegExpSource(Handle<JSRegExp> regexp) {
708  // Prints "/" + re.source + "/" +
709  // (re.global?"g":"") + (re.ignorecase?"i":"") + (re.multiline?"m":"")
710  LogMessageBuilder msg(this);
711 
712  Handle<Object> source = GetProperty(regexp, "source");
713  if (!source->IsString()) {
714  msg.Append("no source");
715  return;
716  }
717 
718  switch (regexp->TypeTag()) {
719  case JSRegExp::ATOM:
720  msg.Append('a');
721  break;
722  default:
723  break;
724  }
725  msg.Append('/');
726  msg.AppendDetailed(*Handle<String>::cast(source), false);
727  msg.Append('/');
728 
729  // global flag
730  Handle<Object> global = GetProperty(regexp, "global");
731  if (global->IsTrue()) {
732  msg.Append('g');
733  }
734  // ignorecase flag
735  Handle<Object> ignorecase = GetProperty(regexp, "ignoreCase");
736  if (ignorecase->IsTrue()) {
737  msg.Append('i');
738  }
739  // multiline flag
740  Handle<Object> multiline = GetProperty(regexp, "multiline");
741  if (multiline->IsTrue()) {
742  msg.Append('m');
743  }
744 
745  msg.WriteToLogFile();
746 }
747 
748 
749 void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
750  if (!log_->IsEnabled() || !FLAG_log_regexp) return;
751  LogMessageBuilder msg(this);
752  msg.Append("regexp-compile,");
753  LogRegExpSource(regexp);
754  msg.Append(in_cache ? ",hit\n" : ",miss\n");
755  msg.WriteToLogFile();
756 }
757 
758 
760  if (!log_->IsEnabled() || !FLAG_log_runtime) return;
761  HandleScope scope;
762  LogMessageBuilder msg(this);
763  for (int i = 0; i < format.length(); i++) {
764  char c = format[i];
765  if (c == '%' && i <= format.length() - 2) {
766  i++;
767  ASSERT('0' <= format[i] && format[i] <= '9');
768  MaybeObject* maybe = args->GetElement(format[i] - '0');
769  Object* obj;
770  if (!maybe->ToObject(&obj)) {
771  msg.Append("<exception>");
772  continue;
773  }
774  i++;
775  switch (format[i]) {
776  case 's':
777  msg.AppendDetailed(String::cast(obj), false);
778  break;
779  case 'S':
780  msg.AppendDetailed(String::cast(obj), true);
781  break;
782  case 'r':
783  Logger::LogRegExpSource(Handle<JSRegExp>(JSRegExp::cast(obj)));
784  break;
785  case 'x':
786  msg.Append("0x%x", Smi::cast(obj)->value());
787  break;
788  case 'i':
789  msg.Append("%i", Smi::cast(obj)->value());
790  break;
791  default:
792  UNREACHABLE();
793  }
794  } else {
795  msg.Append(c);
796  }
797  }
798  msg.Append('\n');
799  msg.WriteToLogFile();
800 }
801 
802 
803 void Logger::ApiIndexedSecurityCheck(uint32_t index) {
804  if (!log_->IsEnabled() || !FLAG_log_api) return;
805  ApiEvent("api,check-security,%u\n", index);
806 }
807 
808 
809 void Logger::ApiNamedPropertyAccess(const char* tag,
810  JSObject* holder,
811  Object* name) {
812  ASSERT(name->IsString());
813  if (!log_->IsEnabled() || !FLAG_log_api) return;
814  String* class_name_obj = holder->class_name();
815  SmartArrayPointer<char> class_name =
817  SmartArrayPointer<char> property_name =
819  ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
820 }
821 
822 void Logger::ApiIndexedPropertyAccess(const char* tag,
823  JSObject* holder,
824  uint32_t index) {
825  if (!log_->IsEnabled() || !FLAG_log_api) return;
826  String* class_name_obj = holder->class_name();
827  SmartArrayPointer<char> class_name =
829  ApiEvent("api,%s,\"%s\",%u\n", tag, *class_name, index);
830 }
831 
832 void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
833  if (!log_->IsEnabled() || !FLAG_log_api) return;
834  String* class_name_obj = object->class_name();
835  SmartArrayPointer<char> class_name =
837  ApiEvent("api,%s,\"%s\"\n", tag, *class_name);
838 }
839 
840 
841 void Logger::ApiEntryCall(const char* name) {
842  if (!log_->IsEnabled() || !FLAG_log_api) return;
843  ApiEvent("api,%s\n", name);
844 }
845 
846 
847 void Logger::NewEvent(const char* name, void* object, size_t size) {
848  if (!log_->IsEnabled() || !FLAG_log) return;
849  LogMessageBuilder msg(this);
850  msg.Append("new,%s,0x%" V8PRIxPTR ",%u\n", name, object,
851  static_cast<unsigned int>(size));
852  msg.WriteToLogFile();
853 }
854 
855 
856 void Logger::DeleteEvent(const char* name, void* object) {
857  if (!log_->IsEnabled() || !FLAG_log) return;
858  LogMessageBuilder msg(this);
859  msg.Append("delete,%s,0x%" V8PRIxPTR "\n", name, object);
860  msg.WriteToLogFile();
861 }
862 
863 
864 void Logger::NewEventStatic(const char* name, void* object, size_t size) {
865  LOGGER->NewEvent(name, object, size);
866 }
867 
868 
869 void Logger::DeleteEventStatic(const char* name, void* object) {
870  LOGGER->DeleteEvent(name, object);
871 }
872 
873 void Logger::CallbackEventInternal(const char* prefix, const char* name,
874  Address entry_point) {
875  if (!log_->IsEnabled() || !FLAG_log_code) return;
876  LogMessageBuilder msg(this);
877  msg.Append("%s,%s,",
878  kLogEventsNames[CODE_CREATION_EVENT],
879  kLogEventsNames[CALLBACK_TAG]);
880  msg.AppendAddress(entry_point);
881  msg.Append(",1,\"%s%s\"", prefix, name);
882  msg.Append('\n');
883  msg.WriteToLogFile();
884 }
885 
886 
887 void Logger::CallbackEvent(String* name, Address entry_point) {
888  if (!log_->IsEnabled() || !FLAG_log_code) return;
891  CallbackEventInternal("", *str, entry_point);
892 }
893 
894 
895 void Logger::GetterCallbackEvent(String* name, Address entry_point) {
896  if (!log_->IsEnabled() || !FLAG_log_code) return;
899  CallbackEventInternal("get ", *str, entry_point);
900 }
901 
902 
903 void Logger::SetterCallbackEvent(String* name, Address entry_point) {
904  if (!log_->IsEnabled() || !FLAG_log_code) return;
907  CallbackEventInternal("set ", *str, entry_point);
908 }
909 
910 
912  Code* code,
913  const char* comment) {
914  if (!is_logging_code_events()) return;
915  if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
916  name_buffer_->Reset();
917  name_buffer_->AppendBytes(kLogEventsNames[tag]);
918  name_buffer_->AppendByte(':');
919  name_buffer_->AppendBytes(comment);
920  }
921  if (code_event_handler_ != NULL) {
922  IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
923  }
924  if (!log_->IsEnabled()) return;
925  if (FLAG_ll_prof) {
926  LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
927  }
928  if (Serializer::enabled()) {
929  RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
930  }
931  if (!FLAG_log_code) return;
932  LogMessageBuilder msg(this);
933  msg.Append("%s,%s,",
934  kLogEventsNames[CODE_CREATION_EVENT],
935  kLogEventsNames[tag]);
936  msg.AppendAddress(code->address());
937  msg.Append(",%d,\"", code->ExecutableSize());
938  for (const char* p = comment; *p != '\0'; p++) {
939  if (*p == '"') {
940  msg.Append('\\');
941  }
942  msg.Append(*p);
943  }
944  msg.Append('"');
945  msg.Append('\n');
946  msg.WriteToLogFile();
947 }
948 
949 
951  Code* code,
952  String* name) {
953  if (!is_logging_code_events()) return;
954  if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
955  name_buffer_->Reset();
956  name_buffer_->AppendBytes(kLogEventsNames[tag]);
957  name_buffer_->AppendByte(':');
958  name_buffer_->AppendString(name);
959  }
960  if (code_event_handler_ != NULL) {
961  IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
962  }
963  if (!log_->IsEnabled()) return;
964  if (FLAG_ll_prof) {
965  LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
966  }
967  if (Serializer::enabled()) {
968  RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
969  }
970  if (!FLAG_log_code) return;
971  LogMessageBuilder msg(this);
972  msg.Append("%s,%s,",
973  kLogEventsNames[CODE_CREATION_EVENT],
974  kLogEventsNames[tag]);
975  msg.AppendAddress(code->address());
976  msg.Append(",%d,\"", code->ExecutableSize());
977  msg.AppendDetailed(name, false);
978  msg.Append('"');
979  msg.Append('\n');
980  msg.WriteToLogFile();
981 }
982 
983 
984 // ComputeMarker must only be used when SharedFunctionInfo is known.
985 static const char* ComputeMarker(Code* code) {
986  switch (code->kind()) {
987  case Code::FUNCTION: return code->optimizable() ? "~" : "";
988  case Code::OPTIMIZED_FUNCTION: return "*";
989  default: return "";
990  }
991 }
992 
993 
995  Code* code,
996  SharedFunctionInfo* shared,
997  String* name) {
998  if (!is_logging_code_events()) return;
999  if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
1000  name_buffer_->Reset();
1001  name_buffer_->AppendBytes(kLogEventsNames[tag]);
1002  name_buffer_->AppendByte(':');
1003  name_buffer_->AppendBytes(ComputeMarker(code));
1004  name_buffer_->AppendString(name);
1005  }
1006  if (code_event_handler_ != NULL) {
1007  IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
1008  }
1009  if (!log_->IsEnabled()) return;
1010  if (FLAG_ll_prof) {
1011  LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
1012  }
1013  if (Serializer::enabled()) {
1014  RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
1015  }
1016  if (!FLAG_log_code) return;
1017  if (code == Isolate::Current()->builtins()->builtin(
1018  Builtins::kLazyCompile))
1019  return;
1020 
1021  LogMessageBuilder msg(this);
1024  msg.Append("%s,%s,",
1025  kLogEventsNames[CODE_CREATION_EVENT],
1026  kLogEventsNames[tag]);
1027  msg.AppendAddress(code->address());
1028  msg.Append(",%d,\"%s\",", code->ExecutableSize(), *str);
1029  msg.AppendAddress(shared->address());
1030  msg.Append(",%s", ComputeMarker(code));
1031  msg.Append('\n');
1032  msg.WriteToLogFile();
1033 }
1034 
1035 
1036 // Although, it is possible to extract source and line from
1037 // the SharedFunctionInfo object, we left it to caller
1038 // to leave logging functions free from heap allocations.
1040  Code* code,
1041  SharedFunctionInfo* shared,
1042  String* source, int line) {
1043  if (!is_logging_code_events()) return;
1044  if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
1045  name_buffer_->Reset();
1046  name_buffer_->AppendBytes(kLogEventsNames[tag]);
1047  name_buffer_->AppendByte(':');
1048  name_buffer_->AppendBytes(ComputeMarker(code));
1049  name_buffer_->AppendString(shared->DebugName());
1050  name_buffer_->AppendByte(' ');
1051  name_buffer_->AppendString(source);
1052  name_buffer_->AppendByte(':');
1053  name_buffer_->AppendInt(line);
1054  }
1055  if (code_event_handler_ != NULL) {
1056  IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
1057  }
1058  if (!log_->IsEnabled()) return;
1059  if (FLAG_ll_prof) {
1060  LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
1061  }
1062  if (Serializer::enabled()) {
1063  RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
1064  }
1065  if (!FLAG_log_code) return;
1066  LogMessageBuilder msg(this);
1069  SmartArrayPointer<char> sourcestr =
1071  msg.Append("%s,%s,",
1072  kLogEventsNames[CODE_CREATION_EVENT],
1073  kLogEventsNames[tag]);
1074  msg.AppendAddress(code->address());
1075  msg.Append(",%d,\"%s %s:%d\",",
1076  code->ExecutableSize(),
1077  *name,
1078  *sourcestr,
1079  line);
1080  msg.AppendAddress(shared->address());
1081  msg.Append(",%s", ComputeMarker(code));
1082  msg.Append('\n');
1083  msg.WriteToLogFile();
1084 }
1085 
1086 
1087 void Logger::CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count) {
1088  if (!is_logging_code_events()) return;
1089  if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
1090  name_buffer_->Reset();
1091  name_buffer_->AppendBytes(kLogEventsNames[tag]);
1092  name_buffer_->AppendByte(':');
1093  name_buffer_->AppendInt(args_count);
1094  }
1095  if (code_event_handler_ != NULL) {
1096  IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
1097  }
1098  if (!log_->IsEnabled()) return;
1099  if (FLAG_ll_prof) {
1100  LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
1101  }
1102  if (Serializer::enabled()) {
1103  RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
1104  }
1105  if (!FLAG_log_code) return;
1106  LogMessageBuilder msg(this);
1107  msg.Append("%s,%s,",
1108  kLogEventsNames[CODE_CREATION_EVENT],
1109  kLogEventsNames[tag]);
1110  msg.AppendAddress(code->address());
1111  msg.Append(",%d,\"args_count: %d\"", code->ExecutableSize(), args_count);
1112  msg.Append('\n');
1113  msg.WriteToLogFile();
1114 }
1115 
1116 
1118  if (!log_->IsEnabled() || !FLAG_ll_prof) return;
1119  LowLevelLogWriteBytes(&kCodeMovingGCTag, sizeof(kCodeMovingGCTag));
1121 }
1122 
1123 
1125  if (!is_logging_code_events()) return;
1126  if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
1127  name_buffer_->Reset();
1128  name_buffer_->AppendBytes(kLogEventsNames[REG_EXP_TAG]);
1129  name_buffer_->AppendByte(':');
1130  name_buffer_->AppendString(source);
1131  }
1132  if (code_event_handler_ != NULL) {
1133  IssueCodeAddedEvent(code, name_buffer_->get(), name_buffer_->size());
1134  }
1135  if (!log_->IsEnabled()) return;
1136  if (FLAG_ll_prof) {
1137  LowLevelCodeCreateEvent(code, name_buffer_->get(), name_buffer_->size());
1138  }
1139  if (Serializer::enabled()) {
1140  RegisterSnapshotCodeName(code, name_buffer_->get(), name_buffer_->size());
1141  }
1142  if (!FLAG_log_code) return;
1143  LogMessageBuilder msg(this);
1144  msg.Append("%s,%s,",
1145  kLogEventsNames[CODE_CREATION_EVENT],
1146  kLogEventsNames[REG_EXP_TAG]);
1147  msg.AppendAddress(code->address());
1148  msg.Append(",%d,\"", code->ExecutableSize());
1149  msg.AppendDetailed(source, false);
1150  msg.Append('\"');
1151  msg.Append('\n');
1152  msg.WriteToLogFile();
1153 }
1154 
1155 
1157  if (code_event_handler_ != NULL) IssueCodeMovedEvent(from, to);
1158  if (!log_->IsEnabled()) return;
1159  if (FLAG_ll_prof) LowLevelCodeMoveEvent(from, to);
1160  if (Serializer::enabled() && address_to_name_map_ != NULL) {
1161  address_to_name_map_->Move(from, to);
1162  }
1163  MoveEventInternal(CODE_MOVE_EVENT, from, to);
1164 }
1165 
1166 
1168  if (code_event_handler_ != NULL) IssueCodeRemovedEvent(from);
1169  if (!log_->IsEnabled()) return;
1170  if (FLAG_ll_prof) LowLevelCodeDeleteEvent(from);
1171  if (Serializer::enabled() && address_to_name_map_ != NULL) {
1172  address_to_name_map_->Remove(from);
1173  }
1174  DeleteEventInternal(CODE_DELETE_EVENT, from);
1175 }
1176 
1177 
1179  if (!log_->IsEnabled()) return;
1180  if (FLAG_ll_prof) LowLevelSnapshotPositionEvent(addr, pos);
1181  if (Serializer::enabled() && address_to_name_map_ != NULL) {
1182  const char* code_name = address_to_name_map_->Lookup(addr);
1183  if (code_name == NULL) return; // Not a code object.
1184  LogMessageBuilder msg(this);
1185  msg.Append("%s,%d,\"", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
1186  for (const char* p = code_name; *p != '\0'; ++p) {
1187  if (*p == '"') msg.Append('\\');
1188  msg.Append(*p);
1189  }
1190  msg.Append("\"\n");
1191  msg.WriteToLogFile();
1192  }
1193  if (!FLAG_log_snapshot_positions) return;
1194  LogMessageBuilder msg(this);
1195  msg.Append("%s,", kLogEventsNames[SNAPSHOT_POSITION_EVENT]);
1196  msg.AppendAddress(addr);
1197  msg.Append(",%d", pos);
1198  msg.Append('\n');
1199  msg.WriteToLogFile();
1200 }
1201 
1202 
1204  MoveEventInternal(SHARED_FUNC_MOVE_EVENT, from, to);
1205 }
1206 
1207 
1208 void Logger::MoveEventInternal(LogEventsAndTags event,
1209  Address from,
1210  Address to) {
1211  if (!log_->IsEnabled() || !FLAG_log_code) return;
1212  LogMessageBuilder msg(this);
1213  msg.Append("%s,", kLogEventsNames[event]);
1214  msg.AppendAddress(from);
1215  msg.Append(',');
1216  msg.AppendAddress(to);
1217  msg.Append('\n');
1218  msg.WriteToLogFile();
1219 }
1220 
1221 
1222 void Logger::DeleteEventInternal(LogEventsAndTags event, Address from) {
1223  if (!log_->IsEnabled() || !FLAG_log_code) return;
1224  LogMessageBuilder msg(this);
1225  msg.Append("%s,", kLogEventsNames[event]);
1226  msg.AppendAddress(from);
1227  msg.Append('\n');
1228  msg.WriteToLogFile();
1229 }
1230 
1231 
1232 void Logger::ResourceEvent(const char* name, const char* tag) {
1233  if (!log_->IsEnabled() || !FLAG_log) return;
1234  LogMessageBuilder msg(this);
1235  msg.Append("%s,%s,", name, tag);
1236 
1237  uint32_t sec, usec;
1238  if (OS::GetUserTime(&sec, &usec) != -1) {
1239  msg.Append("%d,%d,", sec, usec);
1240  }
1241  msg.Append("%.0f", OS::TimeCurrentMillis());
1242 
1243  msg.Append('\n');
1244  msg.WriteToLogFile();
1245 }
1246 
1247 
1249  if (!log_->IsEnabled() || !FLAG_log_suspect) return;
1250  LogMessageBuilder msg(this);
1251  String* class_name = obj->IsJSObject()
1252  ? JSObject::cast(obj)->class_name()
1253  : HEAP->empty_string();
1254  msg.Append("suspect-read,");
1255  msg.Append(class_name);
1256  msg.Append(',');
1257  msg.Append('"');
1258  msg.Append(name);
1259  msg.Append('"');
1260  msg.Append('\n');
1261  msg.WriteToLogFile();
1262 }
1263 
1264 
1265 void Logger::HeapSampleBeginEvent(const char* space, const char* kind) {
1266  if (!log_->IsEnabled() || !FLAG_log_gc) return;
1267  LogMessageBuilder msg(this);
1268  // Using non-relative system time in order to be able to synchronize with
1269  // external memory profiling events (e.g. DOM memory size).
1270  msg.Append("heap-sample-begin,\"%s\",\"%s\",%.0f\n",
1271  space, kind, OS::TimeCurrentMillis());
1272  msg.WriteToLogFile();
1273 }
1274 
1275 
1276 void Logger::HeapSampleEndEvent(const char* space, const char* kind) {
1277  if (!log_->IsEnabled() || !FLAG_log_gc) return;
1278  LogMessageBuilder msg(this);
1279  msg.Append("heap-sample-end,\"%s\",\"%s\"\n", space, kind);
1280  msg.WriteToLogFile();
1281 }
1282 
1283 
1284 void Logger::HeapSampleItemEvent(const char* type, int number, int bytes) {
1285  if (!log_->IsEnabled() || !FLAG_log_gc) return;
1286  LogMessageBuilder msg(this);
1287  msg.Append("heap-sample-item,%s,%d,%d\n", type, number, bytes);
1288  msg.WriteToLogFile();
1289 }
1290 
1291 
1292 void Logger::DebugTag(const char* call_site_tag) {
1293  if (!log_->IsEnabled() || !FLAG_log) return;
1294  LogMessageBuilder msg(this);
1295  msg.Append("debug-tag,%s\n", call_site_tag);
1296  msg.WriteToLogFile();
1297 }
1298 
1299 
1300 void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
1301  if (!log_->IsEnabled() || !FLAG_log) return;
1302  StringBuilder s(parameter.length() + 1);
1303  for (int i = 0; i < parameter.length(); ++i) {
1304  s.AddCharacter(static_cast<char>(parameter[i]));
1305  }
1306  char* parameter_string = s.Finalize();
1307  LogMessageBuilder msg(this);
1308  msg.Append("debug-queue-event,%s,%15.3f,%s\n",
1309  event_type,
1311  parameter_string);
1312  DeleteArray(parameter_string);
1313  msg.WriteToLogFile();
1314 }
1315 
1316 
1317 void Logger::TickEvent(TickSample* sample, bool overflow) {
1318  if (!log_->IsEnabled() || !FLAG_prof) return;
1319  LogMessageBuilder msg(this);
1320  msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
1321  msg.AppendAddress(sample->pc);
1322  msg.Append(',');
1323  msg.AppendAddress(sample->sp);
1324  if (sample->has_external_callback) {
1325  msg.Append(",1,");
1326  msg.AppendAddress(sample->external_callback);
1327  } else {
1328  msg.Append(",0,");
1329  msg.AppendAddress(sample->tos);
1330  }
1331  msg.Append(",%d", static_cast<int>(sample->state));
1332  if (overflow) {
1333  msg.Append(",overflow");
1334  }
1335  for (int i = 0; i < sample->frames_count; ++i) {
1336  msg.Append(',');
1337  msg.AppendAddress(sample->stack[i]);
1338  }
1339  msg.Append('\n');
1340  msg.WriteToLogFile();
1341 }
1342 
1343 
1345  return profiler_ == NULL || profiler_->paused();
1346 }
1347 
1348 
1350  if (!log_->IsEnabled()) return;
1351  if (profiler_ != NULL) {
1352  // It is OK to have negative nesting.
1353  if (--cpu_profiler_nesting_ == 0) {
1354  profiler_->pause();
1355  if (FLAG_prof_lazy) {
1356  if (!FLAG_sliding_state_window && !RuntimeProfiler::IsEnabled()) {
1357  ticker_->Stop();
1358  }
1359  FLAG_log_code = false;
1360  LOG(ISOLATE, UncheckedStringEvent("profiler", "pause"));
1361  }
1362  --logging_nesting_;
1363  }
1364  }
1365 }
1366 
1367 
1369  if (!log_->IsEnabled()) return;
1370  if (profiler_ != NULL) {
1371  if (cpu_profiler_nesting_++ == 0) {
1372  ++logging_nesting_;
1373  if (FLAG_prof_lazy) {
1374  profiler_->Engage();
1375  LOG(ISOLATE, UncheckedStringEvent("profiler", "resume"));
1376  FLAG_log_code = true;
1379  if (!FLAG_sliding_state_window && !ticker_->IsActive()) {
1380  ticker_->Start();
1381  }
1382  }
1383  profiler_->resume();
1384  }
1385  }
1386 }
1387 
1388 
1389 // This function can be called when Log's mutex is acquired,
1390 // either from main or Profiler's thread.
1392  PauseProfiler();
1393 }
1394 
1395 
1396 bool Logger::IsProfilerSamplerActive() {
1397  return ticker_->IsActive();
1398 }
1399 
1400 
1401 class EnumerateOptimizedFunctionsVisitor: public OptimizedFunctionVisitor {
1402  public:
1404  Handle<Code>* code_objects,
1405  int* count)
1406  : sfis_(sfis), code_objects_(code_objects), count_(count) { }
1407 
1408  virtual void EnterContext(Context* context) {}
1409  virtual void LeaveContext(Context* context) {}
1410 
1411  virtual void VisitFunction(JSFunction* function) {
1412  SharedFunctionInfo* sfi = SharedFunctionInfo::cast(function->shared());
1413  Object* maybe_script = sfi->script();
1414  if (maybe_script->IsScript()
1415  && !Script::cast(maybe_script)->HasValidSource()) return;
1416  if (sfis_ != NULL) {
1417  sfis_[*count_] = Handle<SharedFunctionInfo>(sfi);
1418  }
1419  if (code_objects_ != NULL) {
1420  ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
1421  code_objects_[*count_] = Handle<Code>(function->code());
1422  }
1423  *count_ = *count_ + 1;
1424  }
1425 
1426  private:
1428  Handle<Code>* code_objects_;
1429  int* count_;
1430 };
1431 
1432 
1433 static int EnumerateCompiledFunctions(Handle<SharedFunctionInfo>* sfis,
1434  Handle<Code>* code_objects) {
1435  HeapIterator iterator;
1436  AssertNoAllocation no_alloc;
1437  int compiled_funcs_count = 0;
1438 
1439  // Iterate the heap to find shared function info objects and record
1440  // the unoptimized code for them.
1441  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1442  if (!obj->IsSharedFunctionInfo()) continue;
1443  SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
1444  if (sfi->is_compiled()
1445  && (!sfi->script()->IsScript()
1446  || Script::cast(sfi->script())->HasValidSource())) {
1447  if (sfis != NULL) {
1448  sfis[compiled_funcs_count] = Handle<SharedFunctionInfo>(sfi);
1449  }
1450  if (code_objects != NULL) {
1451  code_objects[compiled_funcs_count] = Handle<Code>(sfi->code());
1452  }
1453  ++compiled_funcs_count;
1454  }
1455  }
1456 
1457  // Iterate all optimized functions in all contexts.
1458  EnumerateOptimizedFunctionsVisitor visitor(sfis,
1459  code_objects,
1460  &compiled_funcs_count);
1462 
1463  return compiled_funcs_count;
1464 }
1465 
1466 
1467 void Logger::LogCodeObject(Object* object) {
1468  if (FLAG_log_code || FLAG_ll_prof || is_logging_code_events()) {
1469  Code* code_object = Code::cast(object);
1470  LogEventsAndTags tag = Logger::STUB_TAG;
1471  const char* description = "Unknown code from the snapshot";
1472  switch (code_object->kind()) {
1473  case Code::FUNCTION:
1474  case Code::OPTIMIZED_FUNCTION:
1475  return; // We log this later using LogCompiledFunctions.
1476  case Code::UNARY_OP_IC: // fall through
1477  case Code::BINARY_OP_IC: // fall through
1478  case Code::COMPARE_IC: // fall through
1479  case Code::TO_BOOLEAN_IC: // fall through
1480  case Code::STUB:
1481  description =
1482  CodeStub::MajorName(CodeStub::GetMajorKey(code_object), true);
1483  if (description == NULL)
1484  description = "A stub from the snapshot";
1485  tag = Logger::STUB_TAG;
1486  break;
1487  case Code::BUILTIN:
1488  description = "A builtin from the snapshot";
1489  tag = Logger::BUILTIN_TAG;
1490  break;
1491  case Code::KEYED_LOAD_IC:
1492  description = "A keyed load IC from the snapshot";
1493  tag = Logger::KEYED_LOAD_IC_TAG;
1494  break;
1495  case Code::LOAD_IC:
1496  description = "A load IC from the snapshot";
1497  tag = Logger::LOAD_IC_TAG;
1498  break;
1499  case Code::STORE_IC:
1500  description = "A store IC from the snapshot";
1501  tag = Logger::STORE_IC_TAG;
1502  break;
1503  case Code::KEYED_STORE_IC:
1504  description = "A keyed store IC from the snapshot";
1505  tag = Logger::KEYED_STORE_IC_TAG;
1506  break;
1507  case Code::CALL_IC:
1508  description = "A call IC from the snapshot";
1509  tag = Logger::CALL_IC_TAG;
1510  break;
1511  case Code::KEYED_CALL_IC:
1512  description = "A keyed call IC from the snapshot";
1513  tag = Logger::KEYED_CALL_IC_TAG;
1514  break;
1515  }
1516  PROFILE(ISOLATE, CodeCreateEvent(tag, code_object, description));
1517  }
1518 }
1519 
1520 
1521 void Logger::LogCodeInfo() {
1522  if (!log_->IsEnabled() || !FLAG_ll_prof) return;
1523 #if V8_TARGET_ARCH_IA32
1524  const char arch[] = "ia32";
1525 #elif V8_TARGET_ARCH_X64
1526  const char arch[] = "x64";
1527 #elif V8_TARGET_ARCH_ARM
1528  const char arch[] = "arm";
1529 #elif V8_TARGET_ARCH_MIPS
1530  const char arch[] = "mips";
1531 #else
1532  const char arch[] = "unknown";
1533 #endif
1534  LowLevelLogWriteBytes(arch, sizeof(arch));
1535 }
1536 
1537 
1538 void Logger::RegisterSnapshotCodeName(Code* code,
1539  const char* name,
1540  int name_size) {
1542  if (address_to_name_map_ == NULL) {
1543  address_to_name_map_ = new NameMap;
1544  }
1545  address_to_name_map_->Insert(code->address(), name, name_size);
1546 }
1547 
1548 
1549 void Logger::LowLevelCodeCreateEvent(Code* code,
1550  const char* name,
1551  int name_size) {
1552  if (log_->ll_output_handle_ == NULL) return;
1553  LowLevelCodeCreateStruct event;
1554  event.name_size = name_size;
1555  event.code_address = code->instruction_start();
1556  ASSERT(event.code_address == code->address() + Code::kHeaderSize);
1557  event.code_size = code->instruction_size();
1558  LowLevelLogWriteStruct(event);
1559  LowLevelLogWriteBytes(name, name_size);
1560  LowLevelLogWriteBytes(
1561  reinterpret_cast<const char*>(code->instruction_start()),
1562  code->instruction_size());
1563 }
1564 
1565 
1566 void Logger::LowLevelCodeMoveEvent(Address from, Address to) {
1567  if (log_->ll_output_handle_ == NULL) return;
1568  LowLevelCodeMoveStruct event;
1569  event.from_address = from + Code::kHeaderSize;
1570  event.to_address = to + Code::kHeaderSize;
1571  LowLevelLogWriteStruct(event);
1572 }
1573 
1574 
1575 void Logger::LowLevelCodeDeleteEvent(Address from) {
1576  if (log_->ll_output_handle_ == NULL) return;
1577  LowLevelCodeDeleteStruct event;
1578  event.address = from + Code::kHeaderSize;
1579  LowLevelLogWriteStruct(event);
1580 }
1581 
1582 
1583 void Logger::LowLevelSnapshotPositionEvent(Address addr, int pos) {
1584  if (log_->ll_output_handle_ == NULL) return;
1585  LowLevelSnapshotPositionStruct event;
1586  event.address = addr + Code::kHeaderSize;
1587  event.position = pos;
1588  LowLevelLogWriteStruct(event);
1589 }
1590 
1591 
1592 void Logger::LowLevelLogWriteBytes(const char* bytes, int size) {
1593  size_t rv = fwrite(bytes, 1, size, log_->ll_output_handle_);
1594  ASSERT(static_cast<size_t>(size) == rv);
1595  USE(rv);
1596 }
1597 
1598 
1600  HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1601  "Logger::LogCodeObjects");
1602  HeapIterator iterator;
1603  AssertNoAllocation no_alloc;
1604  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1605  if (obj->IsCode()) LogCodeObject(obj);
1606  }
1607 }
1608 
1609 
1611  Handle<Code> code) {
1612  Handle<String> func_name(shared->DebugName());
1613  if (shared->script()->IsScript()) {
1614  Handle<Script> script(Script::cast(shared->script()));
1615  if (script->name()->IsString()) {
1616  Handle<String> script_name(String::cast(script->name()));
1617  int line_num = GetScriptLineNumber(script, shared->start_position());
1618  if (line_num > 0) {
1619  PROFILE(ISOLATE,
1621  Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
1622  *code, *shared,
1623  *script_name, line_num + 1));
1624  } else {
1625  // Can't distinguish eval and script here, so always use Script.
1626  PROFILE(ISOLATE,
1628  Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
1629  *code, *shared, *script_name));
1630  }
1631  } else {
1632  PROFILE(ISOLATE,
1634  Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
1635  *code, *shared, *func_name));
1636  }
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();
1641  if (!raw_call_data->IsUndefined()) {
1642  CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1643  Object* callback_obj = call_data->callback();
1644  Address entry_point = v8::ToCData<Address>(callback_obj);
1645  PROFILE(ISOLATE, CallbackEvent(*func_name, entry_point));
1646  }
1647  } else {
1648  PROFILE(ISOLATE,
1650  Logger::LAZY_COMPILE_TAG, *code, *shared, *func_name));
1651  }
1652 }
1653 
1654 
1656  HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1657  "Logger::LogCompiledFunctions");
1658  HandleScope scope;
1659  const int compiled_funcs_count = EnumerateCompiledFunctions(NULL, NULL);
1660  ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count);
1661  ScopedVector< Handle<Code> > code_objects(compiled_funcs_count);
1662  EnumerateCompiledFunctions(sfis.start(), code_objects.start());
1663 
1664  // During iteration, there can be heap allocation due to
1665  // GetScriptLineNumber call.
1666  for (int i = 0; i < compiled_funcs_count; ++i) {
1667  if (*code_objects[i] == Isolate::Current()->builtins()->builtin(
1668  Builtins::kLazyCompile))
1669  continue;
1670  LogExistingFunction(sfis[i], code_objects[i]);
1671  }
1672 }
1673 
1674 
1676  HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1677  "Logger::LogAccessorCallbacks");
1678  HeapIterator iterator;
1679  AssertNoAllocation no_alloc;
1680  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1681  if (!obj->IsAccessorInfo()) continue;
1682  AccessorInfo* ai = AccessorInfo::cast(obj);
1683  if (!ai->name()->IsString()) continue;
1684  String* name = String::cast(ai->name());
1685  Address getter_entry = v8::ToCData<Address>(ai->getter());
1686  if (getter_entry != 0) {
1687  PROFILE(ISOLATE, GetterCallbackEvent(name, getter_entry));
1688  }
1689  Address setter_entry = v8::ToCData<Address>(ai->setter());
1690  if (setter_entry != 0) {
1691  PROFILE(ISOLATE, SetterCallbackEvent(name, setter_entry));
1692  }
1693  }
1694 }
1695 
1696 
1698  // Tests and EnsureInitialize() can call this twice in a row. It's harmless.
1699  if (is_initialized_) return true;
1700  is_initialized_ = true;
1701 
1702  // --ll-prof implies --log-code and --log-snapshot-positions.
1703  if (FLAG_ll_prof) {
1704  FLAG_log_snapshot_positions = true;
1705  }
1706 
1707  // --prof_lazy controls --log-code, implies --noprof_auto.
1708  if (FLAG_prof_lazy) {
1709  FLAG_log_code = false;
1710  FLAG_prof_auto = false;
1711  }
1712 
1713  // TODO(isolates): this assert introduces cyclic dependency (logger
1714  // -> thread local top -> heap -> logger).
1715  // ASSERT(VMState::is_outermost_external());
1716 
1717  log_->Initialize();
1718 
1719  if (FLAG_ll_prof) LogCodeInfo();
1720 
1721  Isolate* isolate = Isolate::Current();
1722  ticker_ = new Ticker(isolate, kSamplingIntervalMs);
1723 
1724  if (FLAG_sliding_state_window && sliding_state_window_ == NULL) {
1725  sliding_state_window_ = new SlidingStateWindow(isolate);
1726  }
1727 
1728  bool start_logging = FLAG_log || FLAG_log_runtime || FLAG_log_api
1729  || FLAG_log_code || FLAG_log_gc || FLAG_log_handles || FLAG_log_suspect
1730  || FLAG_log_regexp || FLAG_log_state_changes || FLAG_ll_prof;
1731 
1732  if (start_logging) {
1733  logging_nesting_ = 1;
1734  }
1735 
1736  if (FLAG_prof) {
1737  profiler_ = new Profiler(isolate);
1738  if (!FLAG_prof_auto) {
1739  profiler_->pause();
1740  } else {
1741  logging_nesting_ = 1;
1742  }
1743  if (!FLAG_prof_lazy) {
1744  profiler_->Engage();
1745  }
1746  }
1747 
1748  return true;
1749 }
1750 
1751 
1752 void Logger::SetCodeEventHandler(uint32_t options,
1753  JitCodeEventHandler event_handler) {
1754  code_event_handler_ = event_handler;
1755 
1756  if (code_event_handler_ != NULL && (options & kJitCodeEventEnumExisting)) {
1757  HandleScope scope;
1758  LogCodeObjects();
1760  }
1761 }
1762 
1763 
1765  return ticker_;
1766 }
1767 
1768 
1770  ASSERT(ticker_ != NULL);
1771  if (!ticker_->IsActive()) ticker_->Start();
1772 }
1773 
1774 
1776  if (ticker_ != NULL && ticker_->IsActive()) ticker_->Stop();
1777 }
1778 
1779 
1781  if (!is_initialized_) return NULL;
1782  is_initialized_ = false;
1783 
1784  // Stop the profiler before closing the file.
1785  if (profiler_ != NULL) {
1786  profiler_->Disengage();
1787  delete profiler_;
1788  profiler_ = NULL;
1789  }
1790 
1791  delete sliding_state_window_;
1792  sliding_state_window_ = NULL;
1793 
1794  delete ticker_;
1795  ticker_ = NULL;
1796 
1797  return log_->Close();
1798 }
1799 
1800 
1802  // If the ticker is NULL, Logger::SetUp has not been called yet. In
1803  // that case, we set the sliding_state_window flag so that the
1804  // sliding window computation will be started when Logger::SetUp is
1805  // called.
1806  if (ticker_ == NULL) {
1807  FLAG_sliding_state_window = true;
1808  return;
1809  }
1810  // Otherwise, if the sliding state window computation has not been
1811  // started we do it now.
1812  if (sliding_state_window_ == NULL) {
1813  sliding_state_window_ = new SlidingStateWindow(Isolate::Current());
1814  }
1815 }
1816 
1817 // Protects the state below.
1818 static Mutex* active_samplers_mutex = NULL;
1819 
1820 List<Sampler*>* SamplerRegistry::active_samplers_ = NULL;
1821 
1822 
1824  if (!active_samplers_mutex) {
1825  active_samplers_mutex = OS::CreateMutex();
1826  }
1827 }
1828 
1829 
1830 bool SamplerRegistry::IterateActiveSamplers(VisitSampler func, void* param) {
1831  ScopedLock lock(active_samplers_mutex);
1832  for (int i = 0;
1833  ActiveSamplersExist() && i < active_samplers_->length();
1834  ++i) {
1835  func(active_samplers_->at(i), param);
1836  }
1837  return ActiveSamplersExist();
1838 }
1839 
1840 
1841 static void ComputeCpuProfiling(Sampler* sampler, void* flag_ptr) {
1842  bool* flag = reinterpret_cast<bool*>(flag_ptr);
1843  *flag |= sampler->IsProfiling();
1844 }
1845 
1846 
1848  bool flag = false;
1849  if (!IterateActiveSamplers(&ComputeCpuProfiling, &flag)) {
1850  return HAS_NO_SAMPLERS;
1851  }
1852  return flag ? HAS_CPU_PROFILING_SAMPLERS : HAS_SAMPLERS;
1853 }
1854 
1855 
1857  ASSERT(sampler->IsActive());
1858  ScopedLock lock(active_samplers_mutex);
1859  if (active_samplers_ == NULL) {
1860  active_samplers_ = new List<Sampler*>;
1861  } else {
1862  ASSERT(!active_samplers_->Contains(sampler));
1863  }
1864  active_samplers_->Add(sampler);
1865 }
1866 
1867 
1869  ASSERT(sampler->IsActive());
1870  ScopedLock lock(active_samplers_mutex);
1871  ASSERT(active_samplers_ != NULL);
1872  bool removed = active_samplers_->RemoveElement(sampler);
1873  ASSERT(removed);
1874  USE(removed);
1875 }
1876 
1877 } } // namespace v8::internal
byte * Address
Definition: globals.h:157
void LogRuntime(Vector< const char > format, JSArray *args)
Definition: log.cc:759
void PauseProfiler()
Definition: log.cc:1349
static void NewEventStatic(const char *name, void *object, size_t size)
Definition: log.cc:864
void RegExpCodeCreateEvent(Code *code, String *source)
Definition: log.cc:1124
static CallHandlerInfo * cast(Object *obj)
void CodeMoveEvent(Address from, Address to)
Definition: log.cc:1156
#define V8PRIxPTR
Definition: globals.h:189
SlidingStateWindow(Isolate *isolate)
Definition: log.cc:239
virtual void VisitFunction(JSFunction *function)
Definition: log.cc:1411
void GetterCallbackEvent(String *name, Address entry_point)
Definition: log.cc:895
void Move(Address from, Address to)
Definition: log.cc:404
void SetterCallbackEvent(String *name, Address entry_point)
Definition: log.cc:903
static String * cast(Object *obj)
#define LOG(isolate, Call)
Definition: log.h:81
bool IsActive() const
Definition: platform.h:761
bool Remove(TickSample *sample)
Definition: log.cc:104
Isolate * isolate()
Definition: platform.h:763
static void DeleteEventStatic(const char *name, void *object)
Definition: log.cc:869
static void SignalCodeMovingGC()
static Address js_entry_sp(ThreadLocalTop *thread)
Definition: isolate.h:635
static Handle< String > cast(Handle< S > that)
Definition: handles.h:81
void DecreaseProfilingDepth()
Definition: platform.h:758
void EnsureTickerStopped()
Definition: log.cc:1775
Sampler * sampler()
Definition: log.cc:1764
virtual void Tick(TickSample *sample)
Definition: log.cc:197
bool is_logging_code_events()
Definition: log.h:290
static int GetUserTime(uint32_t *secs, uint32_t *usecs)
int int32_t
Definition: unicode.cc:47
void LogCompiledFunctions()
Definition: log.cc:1655
void CodeDeleteEvent(Address from)
Definition: log.cc:1167
static bool enabled()
Definition: serialize.h:481
TickSample * sample
void SetProfiler(Profiler *profiler)
Definition: log.cc:212
void IntPtrTEvent(const char *name, intptr_t value)
Definition: log.cc:624
#define ASSERT(condition)
Definition: checks.h:270
void EnsureTickerStarted()
Definition: log.cc:1769
void ResumeProfiler()
Definition: log.cc:1368
#define PROFILE(isolate, Call)
Definition: cpu-profiler.h:190
int interval() const
Definition: platform.h:739
static Script * cast(Object *obj)
static JSRegExp * cast(Object *obj)
static SharedFunctionInfo * cast(Object *obj)
void ApiNamedSecurityCheck(Object *key)
Definition: log.cc:667
Address stack[kMaxFramesCount]
Definition: platform.h:728
void ClearProfiler()
Definition: log.cc:219
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:282
void HandleEvent(const char *name, Object **location)
Definition: log.cc:645
static Code * cast(Object *obj)
static void RemoveActiveSampler(Sampler *sampler)
Definition: log.cc:1868
static Smi * cast(Object *object)
void ApiIndexedSecurityCheck(uint32_t index)
Definition: log.cc:803
void LogFailure()
Definition: log.cc:1391
void SnapshotPositionEvent(Address addr, int pos)
Definition: log.cc:1178
uint8_t byte
Definition: globals.h:156
SmartArrayPointer< char > ToCString(AllowNullsFlag allow_nulls, RobustnessFlag robustness_flag, int offset, int length, int *length_output=0)
Definition: objects.cc:6233
void AppendBytes(const char *bytes)
Definition: log.cc:488
uint32_t ComputePointerHash(void *ptr)
Definition: utils.h:311
void HeapSampleBeginEvent(const char *space, const char *kind)
Definition: log.cc:1265
static uchar Length(uchar chr, int previous)
Definition: unicode-inl.h:124
#define UNREACHABLE()
Definition: checks.h:50
T * start() const
Definition: utils.h:390
void AppendBytes(const char *bytes, int size)
Definition: log.cc:482
void LogExistingFunction(Handle< SharedFunctionInfo > shared, Handle< Code > code)
Definition: log.cc:1610
void Insert(TickSample *sample)
Definition: log.cc:90
void IncreaseProfilingDepth()
Definition: platform.h:757
bool IsProfiling() const
Definition: platform.h:756
virtual void EnterContext(Context *context)
Definition: log.cc:1408
Profiler(Isolate *isolate)
Definition: log.cc:269
static Address & Address_at(Address addr)
Definition: v8memory.h:71
void DebugEvent(const char *event_type, Vector< uint16_t > parameter)
Definition: log.cc:1300
FILE * TearDown()
Definition: log.cc:1780
void Insert(Address code_address, const char *name, int name_size)
Definition: log.cc:384
Entry * Lookup(void *key, uint32_t hash, bool insert, AllocationPolicy allocator=AllocationPolicy())
Definition: hashmap.h:131
void RegExpCompileEvent(Handle< JSRegExp > regexp, bool in_cache)
Definition: log.cc:749
bool paused() const
Definition: log.cc:116
int length() const
Definition: utils.h:384
bool IsEnabled()
Definition: log-utils.h:53
static Mutex * CreateMutex()
static double TimeCurrentMillis()
static const int kMakeHeapIterableMask
Definition: heap.h:1088
Address external_callback()
Definition: isolate.h:996
#define V8_PTR_PREFIX
Definition: globals.h:181
Ticker(Isolate *isolate, int interval)
Definition: log.cc:190
Definition: v8.h:105
virtual void LeaveContext(Context *context)
Definition: log.cc:1409
bool IsPowerOf2(T x)
Definition: utils.h:50
void EnableSlidingStateWindow()
Definition: log.cc:1801
void ApiNamedPropertyAccess(const char *tag, JSObject *holder, Object *name)
Definition: log.cc:809
activate correct semantics for inheriting readonliness false
Definition: flags.cc:141
static unsigned Encode(char *out, uchar c, int previous)
Definition: unicode-inl.h:82
int StrLength(const char *string)
Definition: utils.h:234
void LogCodeObjects()
Definition: log.cc:1599
void ApiIndexedPropertyAccess(const char *tag, JSObject *holder, uint32_t index)
Definition: log.cc:822
void SharedLibraryEvent(const char *library_path, uintptr_t start, uintptr_t end)
Definition: log.cc:681
void ApiEntryCall(const char *name)
Definition: log.cc:841
void(* JitCodeEventHandler)(const JitCodeEvent *event)
Definition: v8.h:3017
static int SNPrintF(Vector< char > str, const char *format,...)
void HeapSampleEndEvent(const char *space, const char *kind)
Definition: log.cc:1276
int GetScriptLineNumber(Handle< Script > script, int code_pos)
Definition: handles.cc:479
#define ISOLATE
Definition: isolate.h:1435
#define DISABLE_ASAN
Definition: globals.h:359
#define DECLARE_EVENT(ignore1, name)
Definition: log.cc:591
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
Definition: objects.cc:6891
EnumerateOptimizedFunctionsVisitor(Handle< SharedFunctionInfo > *sfis, Handle< Code > *code_objects, int *count)
Definition: log.cc:1403
void CallbackEvent(String *name, Address entry_point)
Definition: log.cc:887
void AddState(StateTag state)
Definition: log.cc:253
static const int kMaxFramesCount
Definition: platform.h:727
void HeapSampleItemEvent(const char *type, int number, int bytes)
Definition: log.cc:1284
void DeleteEvent(const char *name, void *object)
Definition: log.cc:856
uint16_t uc16
Definition: globals.h:259
int ExecutableSize()
Definition: objects.h:4494
static State GetState()
Definition: log.cc:1847
void ApiObjectAccess(const char *tag, JSObject *obj)
Definition: log.cc:832
virtual void Signal()=0
static const int kHeaderSize
Definition: objects.h:4549
friend class Profiler
Definition: log.h:417
static void LogSharedLibraryAddresses()
void * Remove(void *key, uint32_t hash)
Definition: hashmap.h:162
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
Definition: hashmap.h:113
#define HEAP
Definition: isolate.h:1433
static const int kSamplingIntervalMs
Definition: log.h:319
void CodeMovingGCEvent()
Definition: log.cc:1117
static HeapObject * FromAddress(Address address)
Definition: objects-inl.h:1171
void USE(T)
Definition: globals.h:289
static const unsigned kMaxAsciiCharCodeU
Definition: objects.h:7328
static AccessorInfo * cast(Object *obj)
friend class SlidingStateWindow
Definition: log.h:418
static Handle< Object > GetElement(Handle< Object > object, uint32_t index)
Definition: objects.cc:250
virtual void Wait()=0
static void VisitAllOptimizedFunctions(OptimizedFunctionVisitor *visitor)
Definition: deoptimizer.cc:315
Logger * logger()
Definition: isolate.h:828
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if NULL
Definition: flags.cc:301
#define BUILTIN(name)
Definition: builtins.cc:142
void SharedFunctionInfoMoveEvent(Address from, Address to)
Definition: log.cc:1203
void IntEvent(const char *name, int value)
Definition: log.cc:619
static void AddActiveSampler(Sampler *sampler)
Definition: log.cc:1856
void LogAccessorCallbacks()
Definition: log.cc:1675
bool IsProfilerPaused()
Definition: log.cc:1344
void AppendString(String *str)
Definition: log.cc:457
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
friend class LogMessageBuilder
Definition: log.h:415
static bool IterateActiveSamplers(VisitSampler func, void *param)
Definition: log.cc:1830
void Remove(Address code_address)
Definition: log.cc:396
void DeleteArray(T *array)
Definition: allocation.h:91
T Min(T a, T b)
Definition: utils.h:229
const char * Lookup(Address code_address)
Definition: log.cc:391
#define LOGGER
Definition: isolate.h:1436
ThreadLocalTop * thread_local_top()
Definition: isolate.h:839
virtual void DoSampleStack(TickSample *sample)
Definition: log.cc:226
void CodeCreateEvent(LogEventsAndTags tag, Code *code, const char *source)
Definition: log.cc:911
void DebugTag(const char *call_site_tag)
Definition: log.cc:1292
void ClearWindow()
Definition: log.cc:207
void ResourceEvent(const char *name, const char *tag)
Definition: log.cc:1232
static JSObject * cast(Object *obj)
void NewEvent(const char *name, void *object, size_t size)
Definition: log.cc:847
StatsCounter * state_counters(StateTag state)
Definition: v8-counters.h:383
Entry * Next(Entry *p) const
Definition: hashmap.h:243
static const int kNoPreviousCharacter
Definition: unicode.h:132
void SetWindow(SlidingStateWindow *window)
Definition: log.cc:202
static void Trace(Isolate *isolate, TickSample *sample)
Definition: log.cc:148
void SuspectReadEvent(String *name, Object *obj)
Definition: log.cc:1248
#define LOG_EVENTS_AND_TAGS_LIST(V)
Definition: log.h:98
void StringEvent(const char *name, const char *value)
Definition: log.cc:606
void SetCodeEventHandler(uint32_t options, JitCodeEventHandler event_handler)
Definition: log.cc:1752
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset kInstanceClassNameOffset flag
Definition: objects-inl.h:3923