1// Copyright 2012 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#ifndef V8_LOG_H_
29#define V8_LOG_H_
30
31#include "allocation.h"
32#include "objects.h"
33#include "platform.h"
34
35namespace v8 {
36namespace internal {
37
38// Logger is used for collecting logging information from V8 during
39// execution. The result is dumped to a file.
40//
41// Available command line flags:
42//
43//  --log
44// Minimal logging (no API, code, or GC sample events), default is off.
45//
46// --log-all
47// Log all events to the file, default is off.  This is the same as combining
48// --log-api, --log-code, --log-gc, and --log-regexp.
49//
50// --log-api
51// Log API events to the logfile, default is off.  --log-api implies --log.
52//
53// --log-code
54// Log code (create, move, and delete) events to the logfile, default is off.
55// --log-code implies --log.
56//
57// --log-gc
58// Log GC heap samples after each GC that can be processed by hp2ps, default
59// is off.  --log-gc implies --log.
60//
61// --log-regexp
62// Log creation and use of regular expressions, Default is off.
63// --log-regexp implies --log.
64//
65// --logfile <filename>
66// Specify the name of the logfile, default is "v8.log".
67//
68// --prof
69// Collect statistical profiling information (ticks), default is off.  The
70// tick profiler requires code events, so --prof implies --log-code.
71
72// Forward declarations.
73class CodeEventListener;
74class CompilationInfo;
75class CpuProfiler;
76class Isolate;
77class Log;
78class PositionsRecorder;
79class Profiler;
80class Semaphore;
81class Ticker;
82struct TickSample;
83
84#undef LOG
85#define LOG(isolate, Call)                          \
86  do {                                              \
87    v8::internal::Logger* logger =                  \
88        (isolate)->logger();                        \
89    if (logger->is_logging())                       \
90      logger->Call;                                 \
91  } while (false)
92
93#define LOG_CODE_EVENT(isolate, Call)               \
94  do {                                              \
95    v8::internal::Logger* logger =                  \
96        (isolate)->logger();                        \
97    if (logger->is_logging_code_events())           \
98      logger->Call;                                 \
99  } while (false)
100
101
102#define LOG_EVENTS_AND_TAGS_LIST(V)                                     \
103  V(CODE_CREATION_EVENT,            "code-creation")                    \
104  V(CODE_MOVE_EVENT,                "code-move")                        \
105  V(CODE_DELETE_EVENT,              "code-delete")                      \
106  V(CODE_MOVING_GC,                 "code-moving-gc")                   \
107  V(SHARED_FUNC_MOVE_EVENT,         "sfi-move")                         \
108  V(SNAPSHOT_POSITION_EVENT,        "snapshot-pos")                     \
109  V(SNAPSHOT_CODE_NAME_EVENT,       "snapshot-code-name")               \
110  V(TICK_EVENT,                     "tick")                             \
111  V(REPEAT_META_EVENT,              "repeat")                           \
112  V(BUILTIN_TAG,                    "Builtin")                          \
113  V(CALL_DEBUG_BREAK_TAG,           "CallDebugBreak")                   \
114  V(CALL_DEBUG_PREPARE_STEP_IN_TAG, "CallDebugPrepareStepIn")           \
115  V(CALL_IC_TAG,                    "CallIC")                           \
116  V(CALL_INITIALIZE_TAG,            "CallInitialize")                   \
117  V(CALL_MEGAMORPHIC_TAG,           "CallMegamorphic")                  \
118  V(CALL_MISS_TAG,                  "CallMiss")                         \
119  V(CALL_NORMAL_TAG,                "CallNormal")                       \
120  V(CALL_PRE_MONOMORPHIC_TAG,       "CallPreMonomorphic")               \
121  V(KEYED_CALL_DEBUG_BREAK_TAG,     "KeyedCallDebugBreak")              \
122  V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG,                               \
123    "KeyedCallDebugPrepareStepIn")                                      \
124  V(KEYED_CALL_IC_TAG,              "KeyedCallIC")                      \
125  V(KEYED_CALL_INITIALIZE_TAG,      "KeyedCallInitialize")              \
126  V(KEYED_CALL_MEGAMORPHIC_TAG,     "KeyedCallMegamorphic")             \
127  V(KEYED_CALL_MISS_TAG,            "KeyedCallMiss")                    \
128  V(KEYED_CALL_NORMAL_TAG,          "KeyedCallNormal")                  \
129  V(KEYED_CALL_PRE_MONOMORPHIC_TAG, "KeyedCallPreMonomorphic")          \
130  V(CALLBACK_TAG,                   "Callback")                         \
131  V(EVAL_TAG,                       "Eval")                             \
132  V(FUNCTION_TAG,                   "Function")                         \
133  V(KEYED_LOAD_IC_TAG,              "KeyedLoadIC")                      \
134  V(KEYED_LOAD_POLYMORPHIC_IC_TAG,  "KeyedLoadPolymorphicIC")           \
135  V(KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG, "KeyedExternalArrayLoadIC")       \
136  V(KEYED_STORE_IC_TAG,             "KeyedStoreIC")                     \
137  V(KEYED_STORE_POLYMORPHIC_IC_TAG, "KeyedStorePolymorphicIC")          \
138  V(KEYED_EXTERNAL_ARRAY_STORE_IC_TAG, "KeyedExternalArrayStoreIC")     \
139  V(LAZY_COMPILE_TAG,               "LazyCompile")                      \
140  V(LOAD_IC_TAG,                    "LoadIC")                           \
141  V(LOAD_POLYMORPHIC_IC_TAG,        "LoadPolymorphicIC")                \
142  V(REG_EXP_TAG,                    "RegExp")                           \
143  V(SCRIPT_TAG,                     "Script")                           \
144  V(STORE_IC_TAG,                   "StoreIC")                          \
145  V(STORE_POLYMORPHIC_IC_TAG,       "StorePolymorphicIC")               \
146  V(STUB_TAG,                       "Stub")                             \
147  V(NATIVE_FUNCTION_TAG,            "Function")                         \
148  V(NATIVE_LAZY_COMPILE_TAG,        "LazyCompile")                      \
149  V(NATIVE_SCRIPT_TAG,              "Script")
150// Note that 'NATIVE_' cases for functions and scripts are mapped onto
151// original tags when writing to the log.
152
153
154class JitLogger;
155class LowLevelLogger;
156class Sampler;
157
158class Logger {
159 public:
160#define DECLARE_ENUM(enum_item, ignore) enum_item,
161  enum LogEventsAndTags {
162    LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM)
163    NUMBER_OF_LOG_EVENTS
164  };
165#undef DECLARE_ENUM
166
167  // Acquires resources for logging if the right flags are set.
168  bool SetUp(Isolate* isolate);
169
170  // Sets the current code event handler.
171  void SetCodeEventHandler(uint32_t options,
172                           JitCodeEventHandler event_handler);
173
174  Sampler* sampler();
175
176  // Frees resources acquired in SetUp.
177  // When a temporary file is used for the log, returns its stream descriptor,
178  // leaving the file open.
179  FILE* TearDown();
180
181  // Emits an event with a string value -> (name, value).
182  void StringEvent(const char* name, const char* value);
183
184  // Emits an event with an int value -> (name, value).
185  void IntEvent(const char* name, int value);
186  void IntPtrTEvent(const char* name, intptr_t value);
187
188  // Emits an event with an handle value -> (name, location).
189  void HandleEvent(const char* name, Object** location);
190
191  // Emits memory management events for C allocated structures.
192  void NewEvent(const char* name, void* object, size_t size);
193  void DeleteEvent(const char* name, void* object);
194
195  // Static versions of the above, operate on current isolate's logger.
196  // Used in TRACK_MEMORY(TypeName) defined in globals.h
197  static void NewEventStatic(const char* name, void* object, size_t size);
198  static void DeleteEventStatic(const char* name, void* object);
199
200  // Emits an event with a tag, and some resource usage information.
201  // -> (name, tag, <rusage information>).
202  // Currently, the resource usage information is a process time stamp
203  // and a real time timestamp.
204  void ResourceEvent(const char* name, const char* tag);
205
206  // Emits an event that an undefined property was read from an
207  // object.
208  void SuspectReadEvent(Name* name, Object* obj);
209
210  // Emits an event when a message is put on or read from a debugging queue.
211  // DebugTag lets us put a call-site specific label on the event.
212  void DebugTag(const char* call_site_tag);
213  void DebugEvent(const char* event_type, Vector<uint16_t> parameter);
214
215
216  // ==== Events logged by --log-api. ====
217  void ApiNamedSecurityCheck(Object* key);
218  void ApiIndexedSecurityCheck(uint32_t index);
219  void ApiNamedPropertyAccess(const char* tag, JSObject* holder, Object* name);
220  void ApiIndexedPropertyAccess(const char* tag,
221                                JSObject* holder,
222                                uint32_t index);
223  void ApiObjectAccess(const char* tag, JSObject* obj);
224  void ApiEntryCall(const char* name);
225
226
227  // ==== Events logged by --log-code. ====
228  void addCodeEventListener(CodeEventListener* listener);
229  void removeCodeEventListener(CodeEventListener* listener);
230  bool hasCodeEventListener(CodeEventListener* listener);
231
232
233  // Emits a code event for a callback function.
234  void CallbackEvent(Name* name, Address entry_point);
235  void GetterCallbackEvent(Name* name, Address entry_point);
236  void SetterCallbackEvent(Name* name, Address entry_point);
237  // Emits a code create event.
238  void CodeCreateEvent(LogEventsAndTags tag,
239                       Code* code, const char* source);
240  void CodeCreateEvent(LogEventsAndTags tag,
241                       Code* code, Name* name);
242  void CodeCreateEvent(LogEventsAndTags tag,
243                       Code* code,
244                       SharedFunctionInfo* shared,
245                       CompilationInfo* info,
246                       Name* name);
247  void CodeCreateEvent(LogEventsAndTags tag,
248                       Code* code,
249                       SharedFunctionInfo* shared,
250                       CompilationInfo* info,
251                       Name* source, int line);
252  void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
253  void CodeMovingGCEvent();
254  // Emits a code create event for a RegExp.
255  void RegExpCodeCreateEvent(Code* code, String* source);
256  // Emits a code move event.
257  void CodeMoveEvent(Address from, Address to);
258  // Emits a code delete event.
259  void CodeDeleteEvent(Address from);
260  // Emits a code line info add event with Postion type.
261  void CodeLinePosInfoAddPositionEvent(void* jit_handler_data,
262                                       int pc_offset,
263                                       int position);
264  // Emits a code line info add event with StatementPostion type.
265  void CodeLinePosInfoAddStatementPositionEvent(void* jit_handler_data,
266                                                int pc_offset,
267                                                int position);
268  // Emits a code line info start to record event
269  void CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder);
270  // Emits a code line info finish record event.
271  // It's the callee's responsibility to dispose the parameter jit_handler_data.
272  void CodeEndLinePosInfoRecordEvent(Code* code, void* jit_handler_data);
273
274  void SharedFunctionInfoMoveEvent(Address from, Address to);
275
276  void CodeNameEvent(Address addr, int pos, const char* code_name);
277  void SnapshotPositionEvent(Address addr, int pos);
278
279  // ==== Events logged by --log-gc. ====
280  // Heap sampling events: start, end, and individual types.
281  void HeapSampleBeginEvent(const char* space, const char* kind);
282  void HeapSampleEndEvent(const char* space, const char* kind);
283  void HeapSampleItemEvent(const char* type, int number, int bytes);
284  void HeapSampleJSConstructorEvent(const char* constructor,
285                                    int number, int bytes);
286  void HeapSampleJSRetainersEvent(const char* constructor,
287                                         const char* event);
288  void HeapSampleJSProducerEvent(const char* constructor,
289                                 Address* stack);
290  void HeapSampleStats(const char* space, const char* kind,
291                       intptr_t capacity, intptr_t used);
292
293  void SharedLibraryEvent(const char* library_path,
294                          uintptr_t start,
295                          uintptr_t end);
296  void SharedLibraryEvent(const wchar_t* library_path,
297                          uintptr_t start,
298                          uintptr_t end);
299
300  // ==== Events logged by --log-timer-events. ====
301  enum StartEnd { START, END };
302
303  void CodeDeoptEvent(Code* code);
304
305  void TimerEvent(StartEnd se, const char* name);
306
307  static void EnterExternal(Isolate* isolate);
308  static void LeaveExternal(Isolate* isolate);
309
310  class TimerEventScope {
311   public:
312    TimerEventScope(Isolate* isolate, const char* name)
313        : isolate_(isolate), name_(name) {
314      if (FLAG_log_internal_timer_events) LogTimerEvent(START);
315    }
316
317    ~TimerEventScope() {
318      if (FLAG_log_internal_timer_events) LogTimerEvent(END);
319    }
320
321    void LogTimerEvent(StartEnd se);
322
323    static const char* v8_recompile_synchronous;
324    static const char* v8_recompile_parallel;
325    static const char* v8_compile_full_code;
326    static const char* v8_execute;
327    static const char* v8_external;
328
329   private:
330    Isolate* isolate_;
331    const char* name_;
332  };
333
334  // ==== Events logged by --log-regexp ====
335  // Regexp compilation and execution events.
336
337  void RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache);
338
339  // Log an event reported from generated code
340  void LogRuntime(Vector<const char> format, JSArray* args);
341
342  bool is_logging() {
343    return logging_nesting_ > 0;
344  }
345
346  bool is_logging_code_events() {
347    return is_logging() || jit_logger_ != NULL;
348  }
349
350  // Pause/Resume collection of profiling data.
351  // When data collection is paused, CPU Tick events are discarded until
352  // data collection is Resumed.
353  void PauseProfiler();
354  void ResumeProfiler();
355  bool IsProfilerPaused();
356
357  void LogExistingFunction(Handle<SharedFunctionInfo> shared,
358                           Handle<Code> code);
359  // Logs all compiled functions found in the heap.
360  void LogCompiledFunctions();
361  // Logs all accessor callbacks found in the heap.
362  void LogAccessorCallbacks();
363  // Used for logging stubs found in the snapshot.
364  void LogCodeObjects();
365
366  // Converts tag to a corresponding NATIVE_... if the script is native.
367  INLINE(static LogEventsAndTags ToNativeByScript(LogEventsAndTags, Script*));
368
369  // Profiler's sampling interval (in milliseconds).
370#if defined(ANDROID)
371  // Phones and tablets have processors that are much slower than desktop
372  // and laptop computers for which current heuristics are tuned.
373  static const int kSamplingIntervalMs = 5;
374#else
375  static const int kSamplingIntervalMs = 1;
376#endif
377
378  // Callback from Log, stops profiling in case of insufficient resources.
379  void LogFailure();
380
381 private:
382  explicit Logger(Isolate* isolate);
383  ~Logger();
384
385  // Emits the profiler's first message.
386  void ProfilerBeginEvent();
387
388  // Emits callback event messages.
389  void CallbackEventInternal(const char* prefix,
390                             Name* name,
391                             Address entry_point);
392
393  // Internal configurable move event.
394  void MoveEventInternal(LogEventsAndTags event, Address from, Address to);
395
396  // Emits the source code of a regexp. Used by regexp events.
397  void LogRegExpSource(Handle<JSRegExp> regexp);
398
399  // Used for logging stubs found in the snapshot.
400  void LogCodeObject(Object* code_object);
401
402  // Helper method. It resets name_buffer_ and add tag name into it.
403  void InitNameBuffer(LogEventsAndTags tag);
404
405  // Emits a profiler tick event. Used by the profiler thread.
406  void TickEvent(TickSample* sample, bool overflow);
407
408  void ApiEvent(const char* name, ...);
409
410  // Logs a StringEvent regardless of whether FLAG_log is true.
411  void UncheckedStringEvent(const char* name, const char* value);
412
413  // Logs an IntEvent regardless of whether FLAG_log is true.
414  void UncheckedIntEvent(const char* name, int value);
415  void UncheckedIntPtrTEvent(const char* name, intptr_t value);
416
417  Isolate* isolate_;
418
419  // The sampler used by the profiler and the sliding state window.
420  Ticker* ticker_;
421
422  // When the statistical profile is active, profiler_
423  // points to a Profiler, that handles collection
424  // of samples.
425  Profiler* profiler_;
426
427  // An array of log events names.
428  const char* const* log_events_;
429
430  // Internal implementation classes with access to
431  // private members.
432  friend class EventLog;
433  friend class Isolate;
434  friend class TimeLog;
435  friend class Profiler;
436  template <StateTag Tag> friend class VMState;
437
438  friend class LoggerTestHelper;
439
440
441  int logging_nesting_;
442  int cpu_profiler_nesting_;
443
444  Log* log_;
445  LowLevelLogger* ll_logger_;
446  JitLogger* jit_logger_;
447  List<CodeEventListener*> listeners_;
448
449  // Guards against multiple calls to TearDown() that can happen in some tests.
450  // 'true' between SetUp() and TearDown().
451  bool is_initialized_;
452
453  int64_t epoch_;
454
455  friend class CpuProfiler;
456};
457
458
459class CodeEventListener {
460 public:
461  virtual ~CodeEventListener() {}
462
463  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
464                               Code* code,
465                               const char* comment) = 0;
466  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
467                               Code* code,
468                               Name* name) = 0;
469  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
470                               Code* code,
471                               SharedFunctionInfo* shared,
472                               CompilationInfo* info,
473                               Name* name) = 0;
474  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
475                               Code* code,
476                               SharedFunctionInfo* shared,
477                               CompilationInfo* info,
478                               Name* source,
479                               int line) = 0;
480  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
481                               Code* code,
482                               int args_count) = 0;
483  virtual void CallbackEvent(Name* name, Address entry_point) = 0;
484  virtual void GetterCallbackEvent(Name* name, Address entry_point) = 0;
485  virtual void SetterCallbackEvent(Name* name, Address entry_point) = 0;
486  virtual void RegExpCodeCreateEvent(Code* code, String* source) = 0;
487  virtual void CodeMoveEvent(Address from, Address to) = 0;
488  virtual void CodeDeleteEvent(Address from) = 0;
489  virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0;
490  virtual void CodeMovingGCEvent() = 0;
491};
492
493
494class CodeEventLogger : public CodeEventListener {
495 public:
496  CodeEventLogger();
497  virtual ~CodeEventLogger();
498
499  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
500                               Code* code,
501                               const char* comment);
502  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
503                               Code* code,
504                               Name* name);
505  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
506                               Code* code,
507                               int args_count);
508  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
509                               Code* code,
510                               SharedFunctionInfo* shared,
511                               CompilationInfo* info,
512                               Name* name);
513  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
514                               Code* code,
515                               SharedFunctionInfo* shared,
516                               CompilationInfo* info,
517                               Name* source,
518                               int line);
519  virtual void RegExpCodeCreateEvent(Code* code, String* source);
520
521  virtual void CallbackEvent(Name* name, Address entry_point) { }
522  virtual void GetterCallbackEvent(Name* name, Address entry_point) { }
523  virtual void SetterCallbackEvent(Name* name, Address entry_point) { }
524  virtual void SharedFunctionInfoMoveEvent(Address from, Address to) { }
525  virtual void CodeMovingGCEvent() { }
526
527 private:
528  class NameBuffer;
529
530  virtual void LogRecordedBuffer(Code* code,
531                                 SharedFunctionInfo* shared,
532                                 const char* name,
533                                 int length) = 0;
534
535  NameBuffer* name_buffer_;
536};
537
538
539} }  // namespace v8::internal
540
541
542#endif  // V8_LOG_H_
543