1// Copyright 2012 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 35namespace v8 { 36namespace internal { 37 38// Logger is used for collecting logging information from V8 during 39// execution. The result is dumped to a file. 40// 41// Available command line flags: 42// 43// --log 44// Minimal logging (no API, code, or GC sample events), default is off. 45// 46// --log-all 47// Log all events to the file, default is off. This is the same as combining 48// --log-api, --log-code, --log-gc, and --log-regexp. 49// 50// --log-api 51// Log API events to the logfile, default is off. --log-api implies --log. 52// 53// --log-code 54// Log code (create, move, and delete) events to the logfile, default is off. 55// --log-code implies --log. 56// 57// --log-gc 58// Log GC heap samples after each GC that can be processed by hp2ps, default 59// is off. --log-gc implies --log. 60// 61// --log-regexp 62// Log creation and use of regular expressions, Default is off. 63// --log-regexp implies --log. 64// 65// --logfile <filename> 66// Specify the name of the logfile, default is "v8.log". 67// 68// --prof 69// Collect statistical profiling information (ticks), default is off. The 70// tick profiler requires code events, so --prof implies --log-code. 71 72// Forward declarations. 73class CodeEventListener; 74class CompilationInfo; 75class CpuProfiler; 76class Isolate; 77class Log; 78class PositionsRecorder; 79class Profiler; 80class Semaphore; 81class Ticker; 82struct TickSample; 83 84#undef LOG 85#define LOG(isolate, Call) \ 86 do { \ 87 v8::internal::Logger* logger = \ 88 (isolate)->logger(); \ 89 if (logger->is_logging()) \ 90 logger->Call; \ 91 } while (false) 92 93#define LOG_CODE_EVENT(isolate, Call) \ 94 do { \ 95 v8::internal::Logger* logger = \ 96 (isolate)->logger(); \ 97 if (logger->is_logging_code_events()) \ 98 logger->Call; \ 99 } while (false) 100 101 102#define LOG_EVENTS_AND_TAGS_LIST(V) \ 103 V(CODE_CREATION_EVENT, "code-creation") \ 104 V(CODE_MOVE_EVENT, "code-move") \ 105 V(CODE_DELETE_EVENT, "code-delete") \ 106 V(CODE_MOVING_GC, "code-moving-gc") \ 107 V(SHARED_FUNC_MOVE_EVENT, "sfi-move") \ 108 V(SNAPSHOT_POSITION_EVENT, "snapshot-pos") \ 109 V(SNAPSHOT_CODE_NAME_EVENT, "snapshot-code-name") \ 110 V(TICK_EVENT, "tick") \ 111 V(REPEAT_META_EVENT, "repeat") \ 112 V(BUILTIN_TAG, "Builtin") \ 113 V(CALL_DEBUG_BREAK_TAG, "CallDebugBreak") \ 114 V(CALL_DEBUG_PREPARE_STEP_IN_TAG, "CallDebugPrepareStepIn") \ 115 V(CALL_IC_TAG, "CallIC") \ 116 V(CALL_INITIALIZE_TAG, "CallInitialize") \ 117 V(CALL_MEGAMORPHIC_TAG, "CallMegamorphic") \ 118 V(CALL_MISS_TAG, "CallMiss") \ 119 V(CALL_NORMAL_TAG, "CallNormal") \ 120 V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic") \ 121 V(KEYED_CALL_DEBUG_BREAK_TAG, "KeyedCallDebugBreak") \ 122 V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG, \ 123 "KeyedCallDebugPrepareStepIn") \ 124 V(KEYED_CALL_IC_TAG, "KeyedCallIC") \ 125 V(KEYED_CALL_INITIALIZE_TAG, "KeyedCallInitialize") \ 126 V(KEYED_CALL_MEGAMORPHIC_TAG, "KeyedCallMegamorphic") \ 127 V(KEYED_CALL_MISS_TAG, "KeyedCallMiss") \ 128 V(KEYED_CALL_NORMAL_TAG, "KeyedCallNormal") \ 129 V(KEYED_CALL_PRE_MONOMORPHIC_TAG, "KeyedCallPreMonomorphic") \ 130 V(CALLBACK_TAG, "Callback") \ 131 V(EVAL_TAG, "Eval") \ 132 V(FUNCTION_TAG, "Function") \ 133 V(KEYED_LOAD_IC_TAG, "KeyedLoadIC") \ 134 V(KEYED_LOAD_POLYMORPHIC_IC_TAG, "KeyedLoadPolymorphicIC") \ 135 V(KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG, "KeyedExternalArrayLoadIC") \ 136 V(KEYED_STORE_IC_TAG, "KeyedStoreIC") \ 137 V(KEYED_STORE_POLYMORPHIC_IC_TAG, "KeyedStorePolymorphicIC") \ 138 V(KEYED_EXTERNAL_ARRAY_STORE_IC_TAG, "KeyedExternalArrayStoreIC") \ 139 V(LAZY_COMPILE_TAG, "LazyCompile") \ 140 V(LOAD_IC_TAG, "LoadIC") \ 141 V(LOAD_POLYMORPHIC_IC_TAG, "LoadPolymorphicIC") \ 142 V(REG_EXP_TAG, "RegExp") \ 143 V(SCRIPT_TAG, "Script") \ 144 V(STORE_IC_TAG, "StoreIC") \ 145 V(STORE_POLYMORPHIC_IC_TAG, "StorePolymorphicIC") \ 146 V(STUB_TAG, "Stub") \ 147 V(NATIVE_FUNCTION_TAG, "Function") \ 148 V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile") \ 149 V(NATIVE_SCRIPT_TAG, "Script") 150// Note that 'NATIVE_' cases for functions and scripts are mapped onto 151// original tags when writing to the log. 152 153 154class JitLogger; 155class LowLevelLogger; 156class Sampler; 157 158class Logger { 159 public: 160#define DECLARE_ENUM(enum_item, ignore) enum_item, 161 enum LogEventsAndTags { 162 LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM) 163 NUMBER_OF_LOG_EVENTS 164 }; 165#undef DECLARE_ENUM 166 167 // Acquires resources for logging if the right flags are set. 168 bool SetUp(Isolate* isolate); 169 170 // Sets the current code event handler. 171 void SetCodeEventHandler(uint32_t options, 172 JitCodeEventHandler event_handler); 173 174 Sampler* sampler(); 175 176 // Frees resources acquired in SetUp. 177 // When a temporary file is used for the log, returns its stream descriptor, 178 // leaving the file open. 179 FILE* TearDown(); 180 181 // Emits an event with a string value -> (name, value). 182 void StringEvent(const char* name, const char* value); 183 184 // Emits an event with an int value -> (name, value). 185 void IntEvent(const char* name, int value); 186 void IntPtrTEvent(const char* name, intptr_t value); 187 188 // Emits an event with an handle value -> (name, location). 189 void HandleEvent(const char* name, Object** location); 190 191 // Emits memory management events for C allocated structures. 192 void NewEvent(const char* name, void* object, size_t size); 193 void DeleteEvent(const char* name, void* object); 194 195 // Static versions of the above, operate on current isolate's logger. 196 // Used in TRACK_MEMORY(TypeName) defined in globals.h 197 static void NewEventStatic(const char* name, void* object, size_t size); 198 static void DeleteEventStatic(const char* name, void* object); 199 200 // Emits an event with a tag, and some resource usage information. 201 // -> (name, tag, <rusage information>). 202 // Currently, the resource usage information is a process time stamp 203 // and a real time timestamp. 204 void ResourceEvent(const char* name, const char* tag); 205 206 // Emits an event that an undefined property was read from an 207 // object. 208 void SuspectReadEvent(Name* name, Object* obj); 209 210 // Emits an event when a message is put on or read from a debugging queue. 211 // DebugTag lets us put a call-site specific label on the event. 212 void DebugTag(const char* call_site_tag); 213 void DebugEvent(const char* event_type, Vector<uint16_t> parameter); 214 215 216 // ==== Events logged by --log-api. ==== 217 void ApiNamedSecurityCheck(Object* key); 218 void ApiIndexedSecurityCheck(uint32_t index); 219 void ApiNamedPropertyAccess(const char* tag, JSObject* holder, Object* name); 220 void ApiIndexedPropertyAccess(const char* tag, 221 JSObject* holder, 222 uint32_t index); 223 void ApiObjectAccess(const char* tag, JSObject* obj); 224 void ApiEntryCall(const char* name); 225 226 227 // ==== Events logged by --log-code. ==== 228 void addCodeEventListener(CodeEventListener* listener); 229 void removeCodeEventListener(CodeEventListener* listener); 230 bool hasCodeEventListener(CodeEventListener* listener); 231 232 233 // Emits a code event for a callback function. 234 void CallbackEvent(Name* name, Address entry_point); 235 void GetterCallbackEvent(Name* name, Address entry_point); 236 void SetterCallbackEvent(Name* name, Address entry_point); 237 // Emits a code create event. 238 void CodeCreateEvent(LogEventsAndTags tag, 239 Code* code, const char* source); 240 void CodeCreateEvent(LogEventsAndTags tag, 241 Code* code, Name* name); 242 void CodeCreateEvent(LogEventsAndTags tag, 243 Code* code, 244 SharedFunctionInfo* shared, 245 CompilationInfo* info, 246 Name* name); 247 void CodeCreateEvent(LogEventsAndTags tag, 248 Code* code, 249 SharedFunctionInfo* shared, 250 CompilationInfo* info, 251 Name* source, int line); 252 void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count); 253 void CodeMovingGCEvent(); 254 // Emits a code create event for a RegExp. 255 void RegExpCodeCreateEvent(Code* code, String* source); 256 // Emits a code move event. 257 void CodeMoveEvent(Address from, Address to); 258 // Emits a code delete event. 259 void CodeDeleteEvent(Address from); 260 // Emits a code line info add event with Postion type. 261 void CodeLinePosInfoAddPositionEvent(void* jit_handler_data, 262 int pc_offset, 263 int position); 264 // Emits a code line info add event with StatementPostion type. 265 void CodeLinePosInfoAddStatementPositionEvent(void* jit_handler_data, 266 int pc_offset, 267 int position); 268 // Emits a code line info start to record event 269 void CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder); 270 // Emits a code line info finish record event. 271 // It's the callee's responsibility to dispose the parameter jit_handler_data. 272 void CodeEndLinePosInfoRecordEvent(Code* code, void* jit_handler_data); 273 274 void SharedFunctionInfoMoveEvent(Address from, Address to); 275 276 void CodeNameEvent(Address addr, int pos, const char* code_name); 277 void SnapshotPositionEvent(Address addr, int pos); 278 279 // ==== Events logged by --log-gc. ==== 280 // Heap sampling events: start, end, and individual types. 281 void HeapSampleBeginEvent(const char* space, const char* kind); 282 void HeapSampleEndEvent(const char* space, const char* kind); 283 void HeapSampleItemEvent(const char* type, int number, int bytes); 284 void HeapSampleJSConstructorEvent(const char* constructor, 285 int number, int bytes); 286 void HeapSampleJSRetainersEvent(const char* constructor, 287 const char* event); 288 void HeapSampleJSProducerEvent(const char* constructor, 289 Address* stack); 290 void HeapSampleStats(const char* space, const char* kind, 291 intptr_t capacity, intptr_t used); 292 293 void SharedLibraryEvent(const char* library_path, 294 uintptr_t start, 295 uintptr_t end); 296 void SharedLibraryEvent(const wchar_t* library_path, 297 uintptr_t start, 298 uintptr_t end); 299 300 // ==== Events logged by --log-timer-events. ==== 301 enum StartEnd { START, END }; 302 303 void CodeDeoptEvent(Code* code); 304 305 void TimerEvent(StartEnd se, const char* name); 306 307 static void EnterExternal(Isolate* isolate); 308 static void LeaveExternal(Isolate* isolate); 309 310 class TimerEventScope { 311 public: 312 TimerEventScope(Isolate* isolate, const char* name) 313 : isolate_(isolate), name_(name) { 314 if (FLAG_log_internal_timer_events) LogTimerEvent(START); 315 } 316 317 ~TimerEventScope() { 318 if (FLAG_log_internal_timer_events) LogTimerEvent(END); 319 } 320 321 void LogTimerEvent(StartEnd se); 322 323 static const char* v8_recompile_synchronous; 324 static const char* v8_recompile_parallel; 325 static const char* v8_compile_full_code; 326 static const char* v8_execute; 327 static const char* v8_external; 328 329 private: 330 Isolate* isolate_; 331 const char* name_; 332 }; 333 334 // ==== Events logged by --log-regexp ==== 335 // Regexp compilation and execution events. 336 337 void RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache); 338 339 // Log an event reported from generated code 340 void LogRuntime(Vector<const char> format, JSArray* args); 341 342 bool is_logging() { 343 return logging_nesting_ > 0; 344 } 345 346 bool is_logging_code_events() { 347 return is_logging() || jit_logger_ != NULL; 348 } 349 350 // Pause/Resume collection of profiling data. 351 // When data collection is paused, CPU Tick events are discarded until 352 // data collection is Resumed. 353 void PauseProfiler(); 354 void ResumeProfiler(); 355 bool IsProfilerPaused(); 356 357 void LogExistingFunction(Handle<SharedFunctionInfo> shared, 358 Handle<Code> code); 359 // Logs all compiled functions found in the heap. 360 void LogCompiledFunctions(); 361 // Logs all accessor callbacks found in the heap. 362 void LogAccessorCallbacks(); 363 // Used for logging stubs found in the snapshot. 364 void LogCodeObjects(); 365 366 // Converts tag to a corresponding NATIVE_... if the script is native. 367 INLINE(static LogEventsAndTags ToNativeByScript(LogEventsAndTags, Script*)); 368 369 // Profiler's sampling interval (in milliseconds). 370#if defined(ANDROID) 371 // Phones and tablets have processors that are much slower than desktop 372 // and laptop computers for which current heuristics are tuned. 373 static const int kSamplingIntervalMs = 5; 374#else 375 static const int kSamplingIntervalMs = 1; 376#endif 377 378 // Callback from Log, stops profiling in case of insufficient resources. 379 void LogFailure(); 380 381 private: 382 explicit Logger(Isolate* isolate); 383 ~Logger(); 384 385 // Emits the profiler's first message. 386 void ProfilerBeginEvent(); 387 388 // Emits callback event messages. 389 void CallbackEventInternal(const char* prefix, 390 Name* name, 391 Address entry_point); 392 393 // Internal configurable move event. 394 void MoveEventInternal(LogEventsAndTags event, Address from, Address to); 395 396 // Emits the source code of a regexp. Used by regexp events. 397 void LogRegExpSource(Handle<JSRegExp> regexp); 398 399 // Used for logging stubs found in the snapshot. 400 void LogCodeObject(Object* code_object); 401 402 // Helper method. It resets name_buffer_ and add tag name into it. 403 void InitNameBuffer(LogEventsAndTags tag); 404 405 // Emits a profiler tick event. Used by the profiler thread. 406 void TickEvent(TickSample* sample, bool overflow); 407 408 void ApiEvent(const char* name, ...); 409 410 // Logs a StringEvent regardless of whether FLAG_log is true. 411 void UncheckedStringEvent(const char* name, const char* value); 412 413 // Logs an IntEvent regardless of whether FLAG_log is true. 414 void UncheckedIntEvent(const char* name, int value); 415 void UncheckedIntPtrTEvent(const char* name, intptr_t value); 416 417 Isolate* isolate_; 418 419 // The sampler used by the profiler and the sliding state window. 420 Ticker* ticker_; 421 422 // When the statistical profile is active, profiler_ 423 // points to a Profiler, that handles collection 424 // of samples. 425 Profiler* profiler_; 426 427 // An array of log events names. 428 const char* const* log_events_; 429 430 // Internal implementation classes with access to 431 // private members. 432 friend class EventLog; 433 friend class Isolate; 434 friend class TimeLog; 435 friend class Profiler; 436 template <StateTag Tag> friend class VMState; 437 438 friend class LoggerTestHelper; 439 440 441 int logging_nesting_; 442 int cpu_profiler_nesting_; 443 444 Log* log_; 445 LowLevelLogger* ll_logger_; 446 JitLogger* jit_logger_; 447 List<CodeEventListener*> listeners_; 448 449 // Guards against multiple calls to TearDown() that can happen in some tests. 450 // 'true' between SetUp() and TearDown(). 451 bool is_initialized_; 452 453 int64_t epoch_; 454 455 friend class CpuProfiler; 456}; 457 458 459class CodeEventListener { 460 public: 461 virtual ~CodeEventListener() {} 462 463 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, 464 Code* code, 465 const char* comment) = 0; 466 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, 467 Code* code, 468 Name* name) = 0; 469 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, 470 Code* code, 471 SharedFunctionInfo* shared, 472 CompilationInfo* info, 473 Name* name) = 0; 474 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, 475 Code* code, 476 SharedFunctionInfo* shared, 477 CompilationInfo* info, 478 Name* source, 479 int line) = 0; 480 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, 481 Code* code, 482 int args_count) = 0; 483 virtual void CallbackEvent(Name* name, Address entry_point) = 0; 484 virtual void GetterCallbackEvent(Name* name, Address entry_point) = 0; 485 virtual void SetterCallbackEvent(Name* name, Address entry_point) = 0; 486 virtual void RegExpCodeCreateEvent(Code* code, String* source) = 0; 487 virtual void CodeMoveEvent(Address from, Address to) = 0; 488 virtual void CodeDeleteEvent(Address from) = 0; 489 virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0; 490 virtual void CodeMovingGCEvent() = 0; 491}; 492 493 494class CodeEventLogger : public CodeEventListener { 495 public: 496 CodeEventLogger(); 497 virtual ~CodeEventLogger(); 498 499 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, 500 Code* code, 501 const char* comment); 502 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, 503 Code* code, 504 Name* name); 505 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, 506 Code* code, 507 int args_count); 508 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, 509 Code* code, 510 SharedFunctionInfo* shared, 511 CompilationInfo* info, 512 Name* name); 513 virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, 514 Code* code, 515 SharedFunctionInfo* shared, 516 CompilationInfo* info, 517 Name* source, 518 int line); 519 virtual void RegExpCodeCreateEvent(Code* code, String* source); 520 521 virtual void CallbackEvent(Name* name, Address entry_point) { } 522 virtual void GetterCallbackEvent(Name* name, Address entry_point) { } 523 virtual void SetterCallbackEvent(Name* name, Address entry_point) { } 524 virtual void SharedFunctionInfoMoveEvent(Address from, Address to) { } 525 virtual void CodeMovingGCEvent() { } 526 527 private: 528 class NameBuffer; 529 530 virtual void LogRecordedBuffer(Code* code, 531 SharedFunctionInfo* shared, 532 const char* name, 533 int length) = 0; 534 535 NameBuffer* name_buffer_; 536}; 537 538 539} } // namespace v8::internal 540 541 542#endif // V8_LOG_H_ 543