V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
log.h
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 <set>
9 #include <string>
10 
11 #include "include/v8-profiler.h"
12 #include "src/allocation.h"
13 #include "src/base/compiler-specific.h"
14 #include "src/base/platform/elapsed-timer.h"
15 #include "src/base/platform/platform.h"
16 #include "src/code-events.h"
17 #include "src/isolate.h"
18 #include "src/log-utils.h"
19 #include "src/objects.h"
20 #include "src/objects/string.h"
21 
22 namespace v8 {
23 
24 struct TickSample;
25 
26 namespace sampler {
27 class Sampler;
28 }
29 
30 namespace internal {
31 
32 // Logger is used for collecting logging information from V8 during
33 // execution. The result is dumped to a file.
34 //
35 // Available command line flags:
36 //
37 // --log
38 // Minimal logging (no API, code, or GC sample events), default is off.
39 //
40 // --log-all
41 // Log all events to the file, default is off. This is the same as combining
42 // --log-api, --log-code, and --log-regexp.
43 //
44 // --log-api
45 // Log API events to the logfile, default is off. --log-api implies --log.
46 //
47 // --log-code
48 // Log code (create, move, and delete) events to the logfile, default is off.
49 // --log-code 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 // --prof-sampling-interval <microseconds>
63 // The interval between --prof samples, default is 1000 microseconds (5000 on
64 // Android).
65 
66 // Forward declarations.
67 class CodeEventListener;
68 class CpuProfiler;
69 class Isolate;
70 class JitLogger;
71 class Log;
72 class LowLevelLogger;
73 class PerfBasicLogger;
74 class PerfJitLogger;
75 class Profiler;
76 class RuntimeCallTimer;
77 class Ticker;
78 
79 #undef LOG
80 #define LOG(isolate, Call) \
81  do { \
82  v8::internal::Logger* logger = (isolate)->logger(); \
83  if (logger->is_logging()) logger->Call; \
84  } while (false)
85 
86 #define LOG_CODE_EVENT(isolate, Call) \
87  do { \
88  v8::internal::Logger* logger = (isolate)->logger(); \
89  if (logger->is_listening_to_code_events()) logger->Call; \
90  } while (false)
91 
93  public:
94  explicit ExistingCodeLogger(Isolate* isolate,
95  CodeEventListener* listener = nullptr)
96  : isolate_(isolate), listener_(listener) {}
97 
98  void LogCodeObjects();
99 
100  void LogCompiledFunctions();
101  void LogExistingFunction(Handle<SharedFunctionInfo> shared,
103  CodeEventListener::LogEventsAndTags tag =
104  CodeEventListener::LAZY_COMPILE_TAG);
105  void LogCodeObject(Object* object);
106 
107  private:
108  Isolate* isolate_;
109  CodeEventListener* listener_;
110 };
111 
112 class Logger : public CodeEventListener {
113  public:
114  enum StartEnd { START = 0, END = 1, STAMP = 2 };
115 
116  enum class ScriptEventType {
117  kReserveId,
118  kCreate,
119  kDeserialize,
120  kBackgroundCompile,
121  kStreamingCompile
122  };
123 
124  // The separator is used to write an unescaped "," into the log.
125  static const LogSeparator kNext = LogSeparator::kSeparator;
126 
127  // Acquires resources for logging if the right flags are set.
128  bool SetUp(Isolate* isolate);
129 
130  // Sets the current code event handler.
131  void SetCodeEventHandler(uint32_t options,
132  JitCodeEventHandler event_handler);
133 
134  sampler::Sampler* sampler();
135 
136  void StopProfilerThread();
137 
138  // Frees resources acquired in SetUp.
139  // When a temporary file is used for the log, returns its stream descriptor,
140  // leaving the file open.
141  FILE* TearDown();
142 
143  // Emits an event with a string value -> (name, value).
144  void StringEvent(const char* name, const char* value);
145 
146  // Emits an event with an int value -> (name, value).
147  void IntPtrTEvent(const char* name, intptr_t value);
148 
149  // Emits an event with an handle value -> (name, location).
150  void HandleEvent(const char* name, Address* location);
151 
152  // Emits memory management events for C allocated structures.
153  void NewEvent(const char* name, void* object, size_t size);
154  void DeleteEvent(const char* name, void* object);
155 
156  // Emits an event with a tag, and some resource usage information.
157  // -> (name, tag, <rusage information>).
158  // Currently, the resource usage information is a process time stamp
159  // and a real time timestamp.
160  void ResourceEvent(const char* name, const char* tag);
161 
162  // Emits an event that an undefined property was read from an
163  // object.
164  void SuspectReadEvent(Name name, Object* obj);
165 
166  // ==== Events logged by --log-function-events ====
167  void FunctionEvent(const char* reason, int script_id, double time_delta_ms,
168  int start_position = -1, int end_position = -1,
169  String function_name = String());
170  void FunctionEvent(const char* reason, int script_id, double time_delta_ms,
171  int start_position, int end_position,
172  const char* function_name = nullptr,
173  size_t function_name_length = 0);
174 
175  void CompilationCacheEvent(const char* action, const char* cache_type,
176  SharedFunctionInfo* sfi);
177  void ScriptEvent(ScriptEventType type, int script_id);
178  void ScriptDetails(Script* script);
179 
180  // ==== Events logged by --log-api. ====
181  void ApiSecurityCheck();
182  void ApiNamedPropertyAccess(const char* tag, JSObject* holder, Object* name);
183  void ApiIndexedPropertyAccess(const char* tag,
184  JSObject* holder,
185  uint32_t index);
186  void ApiObjectAccess(const char* tag, JSObject* obj);
187  void ApiEntryCall(const char* name);
188 
189  // ==== Events logged by --log-code. ====
190  void AddCodeEventListener(CodeEventListener* listener);
191  void RemoveCodeEventListener(CodeEventListener* listener);
192 
193  // Emits a code event for a callback function.
194  void CallbackEvent(Name name, Address entry_point) override;
195  void GetterCallbackEvent(Name name, Address entry_point) override;
196  void SetterCallbackEvent(Name name, Address entry_point) override;
197  // Emits a code create event.
198  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
199  AbstractCode code, const char* source) override;
200  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
201  AbstractCode code, Name name) override;
202  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
203  AbstractCode code, SharedFunctionInfo* shared,
204  Name name) override;
205  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
206  AbstractCode code, SharedFunctionInfo* shared,
207  Name source, int line, int column) override;
208  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
209  const wasm::WasmCode* code,
210  wasm::WasmName name) override;
211  // Emits a code deoptimization event.
212  void CodeDisableOptEvent(AbstractCode code,
213  SharedFunctionInfo* shared) override;
214  void CodeMovingGCEvent() override;
215  // Emits a code create event for a RegExp.
216  void RegExpCodeCreateEvent(AbstractCode code, String source) override;
217  // Emits a code move event.
218  void CodeMoveEvent(AbstractCode from, AbstractCode to) override;
219  // Emits a code line info record event.
220  void CodeLinePosInfoRecordEvent(Address code_start,
221  ByteArray source_position_table);
222  void CodeLinePosInfoRecordEvent(Address code_start,
223  Vector<const byte> source_position_table);
224 
225  void SharedFunctionInfoMoveEvent(Address from, Address to) override;
226 
227  void CodeNameEvent(Address addr, int pos, const char* code_name);
228 
229  void CodeDeoptEvent(Code code, DeoptimizeKind kind, Address pc,
230  int fp_to_sp_delta) override;
231 
232  void ICEvent(const char* type, bool keyed, Map map, Object* key,
233  char old_state, char new_state, const char* modifier,
234  const char* slow_stub_reason);
235 
236  void MapEvent(const char* type, Map from, Map to,
237  const char* reason = nullptr,
238  HeapObject* name_or_sfi = nullptr);
239  void MapCreate(Map map);
240  void MapDetails(Map map);
241 
242  void SharedLibraryEvent(const std::string& library_path, uintptr_t start,
243  uintptr_t end, intptr_t aslr_slide);
244 
245  void CurrentTimeEvent();
246 
247  V8_EXPORT_PRIVATE void TimerEvent(StartEnd se, const char* name);
248 
249  static void EnterExternal(Isolate* isolate);
250  static void LeaveExternal(Isolate* isolate);
251 
252  static void DefaultEventLoggerSentinel(const char* name, int event) {}
253 
254  V8_INLINE static void CallEventLogger(Isolate* isolate, const char* name,
255  StartEnd se, bool expose_to_api);
256 
257  bool is_logging() {
258  return is_logging_;
259  }
260 
261  bool is_listening_to_code_events() override {
262  return is_logging() || jit_logger_ != nullptr;
263  }
264 
265  // Stop collection of profiling data.
266  // When data collection is paused, CPU Tick events are discarded.
267  void StopProfiler();
268 
269  void LogExistingFunction(Handle<SharedFunctionInfo> shared,
270  Handle<AbstractCode> code);
271  // Logs all compiled functions found in the heap.
272  void LogCompiledFunctions();
273  // Logs all accessor callbacks found in the heap.
274  void LogAccessorCallbacks();
275  // Used for logging stubs found in the snapshot.
276  void LogCodeObjects();
277  // Logs all Maps found on the heap.
278  void LogAllMaps();
279 
280  // Converts tag to a corresponding NATIVE_... if the script is native.
281  V8_INLINE static CodeEventListener::LogEventsAndTags ToNativeByScript(
282  CodeEventListener::LogEventsAndTags, Script*);
283 
284  // Callback from Log, stops profiling in case of insufficient resources.
285  void LogFailure();
286 
287  // Used for logging stubs found in the snapshot.
288  void LogCodeObject(Object* code_object);
289 
290  private:
291  explicit Logger(Isolate* isolate);
292  ~Logger() override;
293 
294  // Emits the profiler's first message.
295  void ProfilerBeginEvent();
296 
297  // Emits callback event messages.
298  void CallbackEventInternal(const char* prefix, Name name,
299  Address entry_point);
300 
301  // Internal configurable move event.
302  void MoveEventInternal(CodeEventListener::LogEventsAndTags event,
303  Address from, Address to);
304 
305  // Helper method. It resets name_buffer_ and add tag name into it.
306  void InitNameBuffer(CodeEventListener::LogEventsAndTags tag);
307 
308  // Emits a profiler tick event. Used by the profiler thread.
309  void TickEvent(TickSample* sample, bool overflow);
310  void RuntimeCallTimerEvent();
311 
312  // Logs a StringEvent regardless of whether FLAG_log is true.
313  void UncheckedStringEvent(const char* name, const char* value);
314 
315  // Logs an IntPtrTEvent regardless of whether FLAG_log is true.
316  void UncheckedIntPtrTEvent(const char* name, intptr_t value);
317 
318  // Logs a scripts sources. Keeps track of all logged scripts to ensure that
319  // each script is logged only once.
320  bool EnsureLogScriptSource(Script* script);
321 
322  Isolate* isolate_;
323 
324  // The sampler used by the profiler and the sliding state window.
325  Ticker* ticker_;
326 
327  // When the statistical profile is active, profiler_
328  // points to a Profiler, that handles collection
329  // of samples.
330  Profiler* profiler_;
331 
332  // An array of log events names.
333  const char* const* log_events_;
334 
335  // Internal implementation classes with access to
336  // private members.
337  friend class EventLog;
338  friend class Isolate;
339  friend class TimeLog;
340  friend class Profiler;
341  template <StateTag Tag> friend class VMState;
342  friend class LoggerTestHelper;
343 
344  bool is_logging_;
345  Log* log_;
346  PerfBasicLogger* perf_basic_logger_;
347  PerfJitLogger* perf_jit_logger_;
348  LowLevelLogger* ll_logger_;
349  JitLogger* jit_logger_;
350  std::set<int> logged_source_code_;
351  uint32_t next_source_info_id_ = 0;
352 
353  // Guards against multiple calls to TearDown() that can happen in some tests.
354  // 'true' between SetUp() and TearDown().
355  bool is_initialized_;
356 
357  ExistingCodeLogger existing_code_logger_;
358 
359  base::ElapsedTimer timer_;
360 
361  friend class CpuProfiler;
362 };
363 
364 #define TIMER_EVENTS_LIST(V) \
365  V(RecompileSynchronous, true) \
366  V(RecompileConcurrent, true) \
367  V(CompileIgnition, true) \
368  V(CompileFullCode, true) \
369  V(OptimizeCode, true) \
370  V(CompileCode, true) \
371  V(CompileCodeBackground, true) \
372  V(DeoptimizeCode, true) \
373  V(Execute, true) \
374  V(External, true)
375 
376 #define V(TimerName, expose) \
377  class TimerEvent##TimerName : public AllStatic { \
378  public: \
379  static const char* name(void* unused = nullptr) { \
380  return "V8." #TimerName; \
381  } \
382  static bool expose_to_api() { return expose; } \
383  };
384 TIMER_EVENTS_LIST(V)
385 #undef V
386 
387 
388 template <class TimerEvent>
390  public:
391  explicit TimerEventScope(Isolate* isolate) : isolate_(isolate) {
392  LogTimerEvent(Logger::START);
393  }
394 
395  ~TimerEventScope() { LogTimerEvent(Logger::END); }
396 
397  private:
398  void LogTimerEvent(Logger::StartEnd se);
399  Isolate* isolate_;
400 };
401 
403  public:
404  explicit CodeEventLogger(Isolate* isolate);
405  ~CodeEventLogger() override;
406 
407  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code,
408  const char* comment) override;
409  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code,
410  Name name) override;
411  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code,
412  SharedFunctionInfo* shared, Name name) override;
413  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code,
414  SharedFunctionInfo* shared, Name source, int line,
415  int column) override;
416  void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code,
417  wasm::WasmName name) override;
418 
419  void RegExpCodeCreateEvent(AbstractCode code, String source) override;
420  void CallbackEvent(Name name, Address entry_point) override {}
421  void GetterCallbackEvent(Name name, Address entry_point) override {}
422  void SetterCallbackEvent(Name name, Address entry_point) override {}
423  void SharedFunctionInfoMoveEvent(Address from, Address to) override {}
424  void CodeMovingGCEvent() override {}
425  void CodeDeoptEvent(Code code, DeoptimizeKind kind, Address pc,
426  int fp_to_sp_delta) override {}
427 
428  protected:
429  Isolate* isolate_;
430 
431  private:
432  class NameBuffer;
433 
434  virtual void LogRecordedBuffer(AbstractCode code, SharedFunctionInfo* shared,
435  const char* name, int length) = 0;
436  virtual void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
437  int length) = 0;
438 
439  NameBuffer* name_buffer_;
440 };
441 
442 struct CodeEvent {
443  Isolate* isolate_;
444  uintptr_t code_start_address;
445  size_t code_size;
446  Handle<String> function_name;
447  Handle<String> script_name;
448  int script_line;
449  int script_column;
450  CodeEventType code_type;
451  const char* comment;
452 };
453 
455  public:
456  explicit ExternalCodeEventListener(Isolate* isolate);
457  ~ExternalCodeEventListener() override;
458 
459  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code,
460  const char* comment) override;
461  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code,
462  Name name) override;
463  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code,
464  SharedFunctionInfo* shared, Name name) override;
465  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code,
466  SharedFunctionInfo* shared, Name source, int line,
467  int column) override;
468  void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code,
469  wasm::WasmName name) override;
470 
471  void RegExpCodeCreateEvent(AbstractCode code, String source) override;
472  void CallbackEvent(Name name, Address entry_point) override {}
473  void GetterCallbackEvent(Name name, Address entry_point) override {}
474  void SetterCallbackEvent(Name name, Address entry_point) override {}
475  void SharedFunctionInfoMoveEvent(Address from, Address to) override {}
476  void CodeMoveEvent(AbstractCode from, AbstractCode to) override {}
477  void CodeDisableOptEvent(AbstractCode code,
478  SharedFunctionInfo* shared) override {}
479  void CodeMovingGCEvent() override {}
480  void CodeDeoptEvent(Code code, DeoptimizeKind kind, Address pc,
481  int fp_to_sp_delta) override {}
482 
483  void StartListening(CodeEventHandler* code_event_handler);
484  void StopListening();
485 
486  bool is_listening_to_code_events() override { return true; }
487 
488  private:
489  void LogExistingCode();
490 
491  bool is_listening_;
492  Isolate* isolate_;
493  v8::CodeEventHandler* code_event_handler_;
494 };
495 
496 } // namespace internal
497 } // namespace v8
498 
499 
500 #endif // V8_LOG_H_
Definition: libplatform.h:13
CodeEventType
Definition: v8-profiler.h:1064