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