log.h revision 257744e915dfc84d6d07a6b2accf8402d9ffc708
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#ifndef V8_LOG_H_
29#define V8_LOG_H_
30
31#include "allocation.h"
32#include "platform.h"
33#include "log-utils.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 HashMap;
74class LogMessageBuilder;
75class Profiler;
76class Semaphore;
77class SlidingStateWindow;
78class Ticker;
79
80#undef LOG
81#ifdef ENABLE_LOGGING_AND_PROFILING
82#define LOG(isolate, Call)                          \
83  do {                                              \
84    v8::internal::Logger* logger =                  \
85        (isolate)->logger();                        \
86    if (logger->is_logging())                       \
87      logger->Call;                                 \
88  } while (false)
89#else
90#define LOG(isolate, Call) ((void) 0)
91#endif
92
93#define LOG_EVENTS_AND_TAGS_LIST(V)                                     \
94  V(CODE_CREATION_EVENT,            "code-creation")                    \
95  V(CODE_MOVE_EVENT,                "code-move")                        \
96  V(CODE_DELETE_EVENT,              "code-delete")                      \
97  V(CODE_MOVING_GC,                 "code-moving-gc")                   \
98  V(SHARED_FUNC_MOVE_EVENT,         "sfi-move")                         \
99  V(SNAPSHOT_POSITION_EVENT,        "snapshot-pos")                     \
100  V(SNAPSHOT_CODE_NAME_EVENT,       "snapshot-code-name")               \
101  V(TICK_EVENT,                     "tick")                             \
102  V(REPEAT_META_EVENT,              "repeat")                           \
103  V(BUILTIN_TAG,                    "Builtin")                          \
104  V(CALL_DEBUG_BREAK_TAG,           "CallDebugBreak")                   \
105  V(CALL_DEBUG_PREPARE_STEP_IN_TAG, "CallDebugPrepareStepIn")           \
106  V(CALL_IC_TAG,                    "CallIC")                           \
107  V(CALL_INITIALIZE_TAG,            "CallInitialize")                   \
108  V(CALL_MEGAMORPHIC_TAG,           "CallMegamorphic")                  \
109  V(CALL_MISS_TAG,                  "CallMiss")                         \
110  V(CALL_NORMAL_TAG,                "CallNormal")                       \
111  V(CALL_PRE_MONOMORPHIC_TAG,       "CallPreMonomorphic")               \
112  V(KEYED_CALL_DEBUG_BREAK_TAG,     "KeyedCallDebugBreak")              \
113  V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG,                               \
114    "KeyedCallDebugPrepareStepIn")                                      \
115  V(KEYED_CALL_IC_TAG,              "KeyedCallIC")                      \
116  V(KEYED_CALL_INITIALIZE_TAG,      "KeyedCallInitialize")              \
117  V(KEYED_CALL_MEGAMORPHIC_TAG,     "KeyedCallMegamorphic")             \
118  V(KEYED_CALL_MISS_TAG,            "KeyedCallMiss")                    \
119  V(KEYED_CALL_NORMAL_TAG,          "KeyedCallNormal")                  \
120  V(KEYED_CALL_PRE_MONOMORPHIC_TAG, "KeyedCallPreMonomorphic")          \
121  V(CALLBACK_TAG,                   "Callback")                         \
122  V(EVAL_TAG,                       "Eval")                             \
123  V(FUNCTION_TAG,                   "Function")                         \
124  V(KEYED_LOAD_IC_TAG,              "KeyedLoadIC")                      \
125  V(KEYED_LOAD_MEGAMORPHIC_IC_TAG,  "KeyedLoadMegamorphicIC")           \
126  V(KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG, "KeyedExternalArrayLoadIC")       \
127  V(KEYED_STORE_IC_TAG,             "KeyedStoreIC")                     \
128  V(KEYED_STORE_MEGAMORPHIC_IC_TAG, "KeyedStoreMegamorphicIC")          \
129  V(KEYED_EXTERNAL_ARRAY_STORE_IC_TAG, "KeyedExternalArrayStoreIC")     \
130  V(LAZY_COMPILE_TAG,               "LazyCompile")                      \
131  V(LOAD_IC_TAG,                    "LoadIC")                           \
132  V(REG_EXP_TAG,                    "RegExp")                           \
133  V(SCRIPT_TAG,                     "Script")                           \
134  V(STORE_IC_TAG,                   "StoreIC")                          \
135  V(STUB_TAG,                       "Stub")                             \
136  V(NATIVE_FUNCTION_TAG,            "Function")                         \
137  V(NATIVE_LAZY_COMPILE_TAG,        "LazyCompile")                      \
138  V(NATIVE_SCRIPT_TAG,              "Script")
139// Note that 'NATIVE_' cases for functions and scripts are mapped onto
140// original tags when writing to the log.
141
142
143class Sampler;
144
145
146class Logger {
147 public:
148#define DECLARE_ENUM(enum_item, ignore) enum_item,
149  enum LogEventsAndTags {
150    LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM)
151    NUMBER_OF_LOG_EVENTS
152  };
153#undef DECLARE_ENUM
154
155  // Acquires resources for logging if the right flags are set.
156  bool Setup();
157
158  void EnsureTickerStarted();
159  void EnsureTickerStopped();
160
161  Sampler* sampler();
162
163  // Frees resources acquired in Setup.
164  void TearDown();
165
166  // Enable the computation of a sliding window of states.
167  void EnableSlidingStateWindow();
168
169  // Emits an event with a string value -> (name, value).
170  void StringEvent(const char* name, const char* value);
171
172  // Emits an event with an int value -> (name, value).
173  void IntEvent(const char* name, int value);
174  void IntPtrTEvent(const char* name, intptr_t value);
175
176  // Emits an event with an handle value -> (name, location).
177  void HandleEvent(const char* name, Object** location);
178
179  // Emits memory management events for C allocated structures.
180  void NewEvent(const char* name, void* object, size_t size);
181  void DeleteEvent(const char* name, void* object);
182
183  // Static versions of the above, operate on current isolate's logger.
184  // Used in TRACK_MEMORY(TypeName) defined in globals.h
185  static void NewEventStatic(const char* name, void* object, size_t size);
186  static void DeleteEventStatic(const char* name, void* object);
187
188  // Emits an event with a tag, and some resource usage information.
189  // -> (name, tag, <rusage information>).
190  // Currently, the resource usage information is a process time stamp
191  // and a real time timestamp.
192  void ResourceEvent(const char* name, const char* tag);
193
194  // Emits an event that an undefined property was read from an
195  // object.
196  void SuspectReadEvent(String* name, Object* obj);
197
198  // Emits an event when a message is put on or read from a debugging queue.
199  // DebugTag lets us put a call-site specific label on the event.
200  void DebugTag(const char* call_site_tag);
201  void DebugEvent(const char* event_type, Vector<uint16_t> parameter);
202
203
204  // ==== Events logged by --log-api. ====
205  void ApiNamedSecurityCheck(Object* key);
206  void ApiIndexedSecurityCheck(uint32_t index);
207  void ApiNamedPropertyAccess(const char* tag, JSObject* holder, Object* name);
208  void ApiIndexedPropertyAccess(const char* tag,
209                                JSObject* holder,
210                                uint32_t index);
211  void ApiObjectAccess(const char* tag, JSObject* obj);
212  void ApiEntryCall(const char* name);
213
214
215  // ==== Events logged by --log-code. ====
216  // Emits a code event for a callback function.
217  void CallbackEvent(String* name, Address entry_point);
218  void GetterCallbackEvent(String* name, Address entry_point);
219  void SetterCallbackEvent(String* name, Address entry_point);
220  // Emits a code create event.
221  void CodeCreateEvent(LogEventsAndTags tag,
222                       Code* code, const char* source);
223  void CodeCreateEvent(LogEventsAndTags tag,
224                       Code* code, String* name);
225  void CodeCreateEvent(LogEventsAndTags tag,
226                       Code* code,
227                       SharedFunctionInfo* shared,
228                       String* name);
229  void CodeCreateEvent(LogEventsAndTags tag,
230                       Code* code,
231                       SharedFunctionInfo* shared,
232                       String* source, int line);
233  void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
234  void CodeMovingGCEvent();
235  // Emits a code create event for a RegExp.
236  void RegExpCodeCreateEvent(Code* code, String* source);
237  // Emits a code move event.
238  void CodeMoveEvent(Address from, Address to);
239  // Emits a code delete event.
240  void CodeDeleteEvent(Address from);
241
242  void SharedFunctionInfoMoveEvent(Address from, Address to);
243
244  void SnapshotPositionEvent(Address addr, int pos);
245
246  // ==== Events logged by --log-gc. ====
247  // Heap sampling events: start, end, and individual types.
248  void HeapSampleBeginEvent(const char* space, const char* kind);
249  void HeapSampleEndEvent(const char* space, const char* kind);
250  void HeapSampleItemEvent(const char* type, int number, int bytes);
251  void HeapSampleJSConstructorEvent(const char* constructor,
252                                    int number, int bytes);
253  void HeapSampleJSRetainersEvent(const char* constructor,
254                                         const char* event);
255  void HeapSampleJSProducerEvent(const char* constructor,
256                                 Address* stack);
257  void HeapSampleStats(const char* space, const char* kind,
258                       intptr_t capacity, intptr_t used);
259
260  void SharedLibraryEvent(const char* library_path,
261                          uintptr_t start,
262                          uintptr_t end);
263  void SharedLibraryEvent(const wchar_t* library_path,
264                          uintptr_t start,
265                          uintptr_t end);
266
267  // ==== Events logged by --log-regexp ====
268  // Regexp compilation and execution events.
269
270  void RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache);
271
272  // Log an event reported from generated code
273  void LogRuntime(Vector<const char> format, JSArray* args);
274
275#ifdef ENABLE_LOGGING_AND_PROFILING
276  bool is_logging() {
277    return logging_nesting_ > 0;
278  }
279
280  // Pause/Resume collection of profiling data.
281  // When data collection is paused, CPU Tick events are discarded until
282  // data collection is Resumed.
283  void PauseProfiler(int flags, int tag);
284  void ResumeProfiler(int flags, int tag);
285  int GetActiveProfilerModules();
286
287  // If logging is performed into a memory buffer, allows to
288  // retrieve previously written messages. See v8.h.
289  int GetLogLines(int from_pos, char* dest_buf, int max_size);
290
291  // Logs all compiled functions found in the heap.
292  void LogCompiledFunctions();
293  // Logs all accessor callbacks found in the heap.
294  void LogAccessorCallbacks();
295  // Used for logging stubs found in the snapshot.
296  void LogCodeObjects();
297
298  // Converts tag to a corresponding NATIVE_... if the script is native.
299  INLINE(static LogEventsAndTags ToNativeByScript(LogEventsAndTags, Script*));
300
301  // Profiler's sampling interval (in milliseconds).
302#if defined(ANDROID)
303  // Phones and tablets have processors that are much slower than desktop
304  // and laptop computers for which current heuristics are tuned.
305  static const int kSamplingIntervalMs = 5;
306#else
307  static const int kSamplingIntervalMs = 1;
308#endif
309
310  // Callback from Log, stops profiling in case of insufficient resources.
311  void LogFailure();
312
313 private:
314  class NameBuffer;
315  class NameMap;
316
317  Logger();
318  ~Logger();
319
320  // Emits the profiler's first message.
321  void ProfilerBeginEvent();
322
323  // Emits callback event messages.
324  void CallbackEventInternal(const char* prefix,
325                             const char* name,
326                             Address entry_point);
327
328  // Internal configurable move event.
329  void MoveEventInternal(LogEventsAndTags event, Address from, Address to);
330
331  // Internal configurable move event.
332  void DeleteEventInternal(LogEventsAndTags event, Address from);
333
334  // Emits the source code of a regexp. Used by regexp events.
335  void LogRegExpSource(Handle<JSRegExp> regexp);
336
337  // Used for logging stubs found in the snapshot.
338  void LogCodeObject(Object* code_object);
339
340  // Emits general information about generated code.
341  void LogCodeInfo();
342
343  void RegisterSnapshotCodeName(Code* code, const char* name, int name_size);
344
345  // Low-level logging support.
346
347  void LowLevelCodeCreateEvent(Code* code, const char* name, int name_size);
348
349  void LowLevelCodeMoveEvent(Address from, Address to);
350
351  void LowLevelCodeDeleteEvent(Address from);
352
353  void LowLevelSnapshotPositionEvent(Address addr, int pos);
354
355  void LowLevelLogWriteBytes(const char* bytes, int size);
356
357  template <typename T>
358  void LowLevelLogWriteStruct(const T& s) {
359    char tag = T::kTag;
360    LowLevelLogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag));
361    LowLevelLogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s));
362  }
363
364  // Emits a profiler tick event. Used by the profiler thread.
365  void TickEvent(TickSample* sample, bool overflow);
366
367  void ApiEvent(const char* name, ...);
368
369  // Logs a StringEvent regardless of whether FLAG_log is true.
370  void UncheckedStringEvent(const char* name, const char* value);
371
372  // Logs an IntEvent regardless of whether FLAG_log is true.
373  void UncheckedIntEvent(const char* name, int value);
374  void UncheckedIntPtrTEvent(const char* name, intptr_t value);
375
376  // Returns whether profiler's sampler is active.
377  bool IsProfilerSamplerActive();
378
379  // The sampler used by the profiler and the sliding state window.
380  Ticker* ticker_;
381
382  // When the statistical profile is active, profiler_
383  // points to a Profiler, that handles collection
384  // of samples.
385  Profiler* profiler_;
386
387  // SlidingStateWindow instance keeping a sliding window of the most
388  // recent VM states.
389  SlidingStateWindow* sliding_state_window_;
390
391  // An array of log events names.
392  const char* const* log_events_;
393
394  // Internal implementation classes with access to
395  // private members.
396  friend class EventLog;
397  friend class Isolate;
398  friend class LogMessageBuilder;
399  friend class TimeLog;
400  friend class Profiler;
401  friend class SlidingStateWindow;
402  friend class StackTracer;
403  friend class VMState;
404
405  friend class LoggerTestHelper;
406
407
408  int logging_nesting_;
409  int cpu_profiler_nesting_;
410  int heap_profiler_nesting_;
411
412  Log* log_;
413
414  NameBuffer* name_buffer_;
415
416  NameMap* address_to_name_map_;
417
418  // Guards against multiple calls to TearDown() that can happen in some tests.
419  // 'true' between Setup() and TearDown().
420  bool is_initialized_;
421
422  // Support for 'incremental addresses' in compressed logs:
423  //  LogMessageBuilder::AppendAddress(Address addr)
424  Address last_address_;
425  //  Logger::TickEvent(...)
426  Address prev_sp_;
427  Address prev_function_;
428  //  Logger::MoveEventInternal(...)
429  Address prev_to_;
430  //  Logger::FunctionCreateEvent(...)
431  Address prev_code_;
432
433  friend class CpuProfiler;
434#else
435  bool is_logging() { return false; }
436#endif
437};
438
439
440// Process wide registry of samplers.
441class SamplerRegistry : public AllStatic {
442 public:
443  enum State {
444    HAS_NO_SAMPLERS,
445    HAS_SAMPLERS,
446    HAS_CPU_PROFILING_SAMPLERS
447  };
448
449  typedef void (*VisitSampler)(Sampler*, void*);
450
451  static State GetState();
452
453  // Iterates over all active samplers keeping the internal lock held.
454  // Returns whether there are any active samplers.
455  static bool IterateActiveSamplers(VisitSampler func, void* param);
456
457  // Adds/Removes an active sampler.
458  static void AddActiveSampler(Sampler* sampler);
459  static void RemoveActiveSampler(Sampler* sampler);
460
461 private:
462  static bool ActiveSamplersExist() {
463    return active_samplers_ != NULL && !active_samplers_->is_empty();
464  }
465
466  static Mutex* mutex_;  // Protects the state below.
467  static List<Sampler*>* active_samplers_;
468
469  DISALLOW_IMPLICIT_CONSTRUCTORS(SamplerRegistry);
470};
471
472
473// Class that extracts stack trace, used for profiling.
474class StackTracer : public AllStatic {
475 public:
476  static void Trace(Isolate* isolate, TickSample* sample);
477};
478
479} }  // namespace v8::internal
480
481
482#endif  // V8_LOG_H_
483