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 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 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 221 bool is_logging() { 222 return is_logging_; 223 } 224 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 }; 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 388 void CallbackEvent(Name* name, Address entry_point) override {} 389 void GetterCallbackEvent(Name* name, Address entry_point) override {} 390 void SetterCallbackEvent(Name* name, Address entry_point) override {} 391 void SharedFunctionInfoMoveEvent(Address from, Address to) override {} 392 void CodeMovingGCEvent() override {} 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