• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_LOG_H_
6 #define V8_LOG_H_
7 
8 #include <string>
9 
10 #include "src/allocation.h"
11 #include "src/base/compiler-specific.h"
12 #include "src/base/platform/elapsed-timer.h"
13 #include "src/base/platform/platform.h"
14 #include "src/code-events.h"
15 #include "src/isolate.h"
16 #include "src/objects.h"
17 
18 namespace v8 {
19 
20 struct TickSample;
21 
22 namespace sampler {
23 class Sampler;
24 }
25 
26 namespace internal {
27 
28 // Logger is used for collecting logging information from V8 during
29 // execution. The result is dumped to a file.
30 //
31 // Available command line flags:
32 //
33 //  --log
34 // Minimal logging (no API, code, or GC sample events), default is off.
35 //
36 // --log-all
37 // Log all events to the file, default is off.  This is the same as combining
38 // --log-api, --log-code, --log-gc, and --log-regexp.
39 //
40 // --log-api
41 // Log API events to the logfile, default is off.  --log-api implies --log.
42 //
43 // --log-code
44 // Log code (create, move, and delete) events to the logfile, default is off.
45 // --log-code implies --log.
46 //
47 // --log-gc
48 // Log GC heap samples after each GC that can be processed by hp2ps, default
49 // is off.  --log-gc implies --log.
50 //
51 // --log-regexp
52 // Log creation and use of regular expressions, Default is off.
53 // --log-regexp implies --log.
54 //
55 // --logfile <filename>
56 // Specify the name of the logfile, default is "v8.log".
57 //
58 // --prof
59 // Collect statistical profiling information (ticks), default is off.  The
60 // tick profiler requires code events, so --prof implies --log-code.
61 
62 // Forward declarations.
63 class CodeEventListener;
64 class CpuProfiler;
65 class Isolate;
66 class JitLogger;
67 class Log;
68 class LowLevelLogger;
69 class PerfBasicLogger;
70 class PerfJitLogger;
71 class Profiler;
72 class ProfilerListener;
73 class RuntimeCallTimer;
74 class Ticker;
75 
76 #undef LOG
77 #define LOG(isolate, Call)                              \
78   do {                                                  \
79     v8::internal::Logger* logger = (isolate)->logger(); \
80     if (logger->is_logging()) logger->Call;             \
81   } while (false)
82 
83 #define LOG_CODE_EVENT(isolate, Call)                   \
84   do {                                                  \
85     v8::internal::Logger* logger = (isolate)->logger(); \
86     if (logger->is_logging_code_events()) logger->Call; \
87   } while (false)
88 
89 class Logger : public CodeEventListener {
90  public:
91   enum StartEnd { START = 0, END = 1 };
92 
93   // Acquires resources for logging if the right flags are set.
94   bool SetUp(Isolate* isolate);
95 
96   // Sets the current code event handler.
97   void SetCodeEventHandler(uint32_t options,
98                            JitCodeEventHandler event_handler);
99 
100   // Sets up ProfilerListener.
101   void SetUpProfilerListener();
102 
103   // Tear down ProfilerListener if it has no observers.
104   void TearDownProfilerListener();
105 
106   sampler::Sampler* sampler();
107 
profiler_listener()108   ProfilerListener* profiler_listener() { return profiler_listener_.get(); }
109 
110   // Frees resources acquired in SetUp.
111   // When a temporary file is used for the log, returns its stream descriptor,
112   // leaving the file open.
113   FILE* TearDown();
114 
115   // Emits an event with a string value -> (name, value).
116   void StringEvent(const char* name, const char* value);
117 
118   // Emits an event with an int value -> (name, value).
119   void IntEvent(const char* name, int value);
120   void IntPtrTEvent(const char* name, intptr_t value);
121 
122   // Emits an event with an handle value -> (name, location).
123   void HandleEvent(const char* name, Object** location);
124 
125   // Emits memory management events for C allocated structures.
126   void NewEvent(const char* name, void* object, size_t size);
127   void DeleteEvent(const char* name, void* object);
128 
129   // Emits an event with a tag, and some resource usage information.
130   // -> (name, tag, <rusage information>).
131   // Currently, the resource usage information is a process time stamp
132   // and a real time timestamp.
133   void ResourceEvent(const char* name, const char* tag);
134 
135   // Emits an event that an undefined property was read from an
136   // object.
137   void SuspectReadEvent(Name* name, Object* obj);
138 
139   // Emits an event when a message is put on or read from a debugging queue.
140   // DebugTag lets us put a call-site specific label on the event.
141   void DebugTag(const char* call_site_tag);
142   void DebugEvent(const char* event_type, Vector<uint16_t> parameter);
143 
144 
145   // ==== Events logged by --log-api. ====
146   void ApiSecurityCheck();
147   void ApiNamedPropertyAccess(const char* tag, JSObject* holder, Object* name);
148   void ApiIndexedPropertyAccess(const char* tag,
149                                 JSObject* holder,
150                                 uint32_t index);
151   void ApiObjectAccess(const char* tag, JSObject* obj);
152   void ApiEntryCall(const char* name);
153 
154   // ==== Events logged by --log-code. ====
155   void addCodeEventListener(CodeEventListener* listener);
156   void removeCodeEventListener(CodeEventListener* listener);
157 
158   // Emits a code event for a callback function.
159   void CallbackEvent(Name* name, Address entry_point);
160   void GetterCallbackEvent(Name* name, Address entry_point);
161   void SetterCallbackEvent(Name* name, Address entry_point);
162   // Emits a code create event.
163   void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
164                        AbstractCode* code, const char* source);
165   void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
166                        AbstractCode* code, Name* name);
167   void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
168                        AbstractCode* code, SharedFunctionInfo* shared,
169                        Name* name);
170   void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
171                        AbstractCode* code, SharedFunctionInfo* shared,
172                        Name* source, int line, int column);
173   void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
174                        AbstractCode* code, int args_count);
175   // Emits a code deoptimization event.
176   void CodeDisableOptEvent(AbstractCode* code, SharedFunctionInfo* shared);
177   void CodeMovingGCEvent();
178   // Emits a code create event for a RegExp.
179   void RegExpCodeCreateEvent(AbstractCode* code, String* source);
180   // Emits a code move event.
181   void CodeMoveEvent(AbstractCode* from, Address to);
182   // Emits a code line info record event.
183   void CodeLinePosInfoRecordEvent(AbstractCode* code,
184                                   ByteArray* source_position_table);
185 
186   void SharedFunctionInfoMoveEvent(Address from, Address to);
187 
188   void CodeNameEvent(Address addr, int pos, const char* code_name);
189 
190   void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta);
191 
192   // ==== Events logged by --log-gc. ====
193   // Heap sampling events: start, end, and individual types.
194   void HeapSampleBeginEvent(const char* space, const char* kind);
195   void HeapSampleEndEvent(const char* space, const char* kind);
196   void HeapSampleItemEvent(const char* type, int number, int bytes);
197   void HeapSampleJSConstructorEvent(const char* constructor,
198                                     int number, int bytes);
199   void HeapSampleJSRetainersEvent(const char* constructor,
200                                          const char* event);
201   void HeapSampleJSProducerEvent(const char* constructor,
202                                  Address* stack);
203   void HeapSampleStats(const char* space, const char* kind,
204                        intptr_t capacity, intptr_t used);
205 
206   void SharedLibraryEvent(const std::string& library_path, uintptr_t start,
207                           uintptr_t end, intptr_t aslr_slide);
208 
209   void CurrentTimeEvent();
210 
211   void TimerEvent(StartEnd se, const char* name);
212 
213   static void EnterExternal(Isolate* isolate);
214   static void LeaveExternal(Isolate* isolate);
215 
DefaultEventLoggerSentinel(const char * name,int event)216   static void DefaultEventLoggerSentinel(const char* name, int event) {}
217 
218   INLINE(static void CallEventLogger(Isolate* isolate, const char* name,
219                                      StartEnd se, bool expose_to_api));
220 
is_logging()221   bool is_logging() {
222     return is_logging_;
223   }
224 
is_logging_code_events()225   bool is_logging_code_events() {
226     return is_logging() || jit_logger_ != NULL;
227   }
228 
229   // Stop collection of profiling data.
230   // When data collection is paused, CPU Tick events are discarded.
231   void StopProfiler();
232 
233   void LogExistingFunction(Handle<SharedFunctionInfo> shared,
234                            Handle<AbstractCode> code);
235   // Logs all compiled functions found in the heap.
236   void LogCompiledFunctions();
237   // Logs all accessor callbacks found in the heap.
238   void LogAccessorCallbacks();
239   // Used for logging stubs found in the snapshot.
240   void LogCodeObjects();
241   // Used for logging bytecode handlers found in the snapshot.
242   void LogBytecodeHandlers();
243 
244   // Converts tag to a corresponding NATIVE_... if the script is native.
245   INLINE(static CodeEventListener::LogEventsAndTags ToNativeByScript(
246       CodeEventListener::LogEventsAndTags, Script*));
247 
248   // Profiler's sampling interval (in milliseconds).
249 #if defined(ANDROID)
250   // Phones and tablets have processors that are much slower than desktop
251   // and laptop computers for which current heuristics are tuned.
252   static const int kSamplingIntervalMs = 5;
253 #else
254   static const int kSamplingIntervalMs = 1;
255 #endif
256 
257   // Callback from Log, stops profiling in case of insufficient resources.
258   void LogFailure();
259 
260  private:
261   explicit Logger(Isolate* isolate);
262   ~Logger();
263 
264   // Emits the profiler's first message.
265   void ProfilerBeginEvent();
266 
267   // Emits callback event messages.
268   void CallbackEventInternal(const char* prefix,
269                              Name* name,
270                              Address entry_point);
271 
272   // Internal configurable move event.
273   void MoveEventInternal(CodeEventListener::LogEventsAndTags event,
274                          Address from, Address to);
275 
276   // Used for logging stubs found in the snapshot.
277   void LogCodeObject(Object* code_object);
278 
279   // Helper method. It resets name_buffer_ and add tag name into it.
280   void InitNameBuffer(CodeEventListener::LogEventsAndTags tag);
281 
282   // Emits a profiler tick event. Used by the profiler thread.
283   void TickEvent(TickSample* sample, bool overflow);
284   void RuntimeCallTimerEvent();
285 
286   PRINTF_FORMAT(2, 3) void ApiEvent(const char* format, ...);
287 
288   // Logs a StringEvent regardless of whether FLAG_log is true.
289   void UncheckedStringEvent(const char* name, const char* value);
290 
291   // Logs an IntEvent regardless of whether FLAG_log is true.
292   void UncheckedIntEvent(const char* name, int value);
293   void UncheckedIntPtrTEvent(const char* name, intptr_t value);
294 
295   Isolate* isolate_;
296 
297   // The sampler used by the profiler and the sliding state window.
298   Ticker* ticker_;
299 
300   // When the statistical profile is active, profiler_
301   // points to a Profiler, that handles collection
302   // of samples.
303   Profiler* profiler_;
304 
305   // An array of log events names.
306   const char* const* log_events_;
307 
308   // Internal implementation classes with access to
309   // private members.
310   friend class EventLog;
311   friend class Isolate;
312   friend class TimeLog;
313   friend class Profiler;
314   template <StateTag Tag> friend class VMState;
315   friend class LoggerTestHelper;
316 
317   bool is_logging_;
318   Log* log_;
319   PerfBasicLogger* perf_basic_logger_;
320   PerfJitLogger* perf_jit_logger_;
321   LowLevelLogger* ll_logger_;
322   JitLogger* jit_logger_;
323   std::unique_ptr<ProfilerListener> profiler_listener_;
324   List<CodeEventListener*> listeners_;
325 
326   // Guards against multiple calls to TearDown() that can happen in some tests.
327   // 'true' between SetUp() and TearDown().
328   bool is_initialized_;
329 
330   base::ElapsedTimer timer_;
331 
332   friend class CpuProfiler;
333 };
334 
335 #define TIMER_EVENTS_LIST(V)    \
336   V(RecompileSynchronous, true) \
337   V(RecompileConcurrent, true)  \
338   V(CompileIgnition, true)      \
339   V(CompileFullCode, true)      \
340   V(OptimizeCode, true)         \
341   V(CompileCode, true)          \
342   V(DeoptimizeCode, true)       \
343   V(Execute, true)              \
344   V(External, true)
345 
346 #define V(TimerName, expose)                                                  \
347   class TimerEvent##TimerName : public AllStatic {                            \
348    public:                                                                    \
349     static const char* name(void* unused = NULL) { return "V8." #TimerName; } \
350     static bool expose_to_api() { return expose; }                            \
351   };
TIMER_EVENTS_LIST(V)352 TIMER_EVENTS_LIST(V)
353 #undef V
354 
355 
356 template <class TimerEvent>
357 class TimerEventScope {
358  public:
359   explicit TimerEventScope(Isolate* isolate) : isolate_(isolate) {
360     LogTimerEvent(Logger::START);
361   }
362 
363   ~TimerEventScope() { LogTimerEvent(Logger::END); }
364 
365  private:
366   void LogTimerEvent(Logger::StartEnd se);
367   Isolate* isolate_;
368 };
369 
370 class CodeEventLogger : public CodeEventListener {
371  public:
372   CodeEventLogger();
373   ~CodeEventLogger() override;
374 
375   void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
376                        const char* comment) override;
377   void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
378                        Name* name) override;
379   void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
380                        int args_count) override;
381   void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
382                        SharedFunctionInfo* shared, Name* name) override;
383   void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
384                        SharedFunctionInfo* shared, Name* source, int line,
385                        int column) override;
386   void RegExpCodeCreateEvent(AbstractCode* code, String* source) override;
387 
CallbackEvent(Name * name,Address entry_point)388   void CallbackEvent(Name* name, Address entry_point) override {}
GetterCallbackEvent(Name * name,Address entry_point)389   void GetterCallbackEvent(Name* name, Address entry_point) override {}
SetterCallbackEvent(Name * name,Address entry_point)390   void SetterCallbackEvent(Name* name, Address entry_point) override {}
SharedFunctionInfoMoveEvent(Address from,Address to)391   void SharedFunctionInfoMoveEvent(Address from, Address to) override {}
CodeMovingGCEvent()392   void CodeMovingGCEvent() override {}
CodeDeoptEvent(Code * code,Address pc,int fp_to_sp_delta)393   void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) override {}
394 
395  private:
396   class NameBuffer;
397 
398   virtual void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo* shared,
399                                  const char* name, int length) = 0;
400 
401   NameBuffer* name_buffer_;
402 };
403 
404 
405 }  // namespace internal
406 }  // namespace v8
407 
408 
409 #endif  // V8_LOG_H_
410