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