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 #include "log-utils.h" 35 36 namespace v8 { 37 namespace internal { 38 39 // Logger is used for collecting logging information from V8 during 40 // execution. The result is dumped to a file. 41 // 42 // Available command line flags: 43 // 44 // --log 45 // Minimal logging (no API, code, or GC sample events), default is off. 46 // 47 // --log-all 48 // Log all events to the file, default is off. This is the same as combining 49 // --log-api, --log-code, --log-gc, and --log-regexp. 50 // 51 // --log-api 52 // Log API events to the logfile, default is off. --log-api implies --log. 53 // 54 // --log-code 55 // Log code (create, move, and delete) events to the logfile, default is off. 56 // --log-code implies --log. 57 // 58 // --log-gc 59 // Log GC heap samples after each GC that can be processed by hp2ps, default 60 // is off. --log-gc implies --log. 61 // 62 // --log-regexp 63 // Log creation and use of regular expressions, Default is off. 64 // --log-regexp implies --log. 65 // 66 // --logfile <filename> 67 // Specify the name of the logfile, default is "v8.log". 68 // 69 // --prof 70 // Collect statistical profiling information (ticks), default is off. The 71 // tick profiler requires code events, so --prof implies --log-code. 72 73 // Forward declarations. 74 class LogMessageBuilder; 75 class Profiler; 76 class Semaphore; 77 class SlidingStateWindow; 78 class Ticker; 79 80 #undef LOG 81 #define LOG(isolate, Call) \ 82 do { \ 83 v8::internal::Logger* logger = \ 84 (isolate)->logger(); \ 85 if (logger->is_logging()) \ 86 logger->Call; \ 87 } while (false) 88 89 #define LOG_EVENTS_AND_TAGS_LIST(V) \ 90 V(CODE_CREATION_EVENT, "code-creation") \ 91 V(CODE_MOVE_EVENT, "code-move") \ 92 V(CODE_DELETE_EVENT, "code-delete") \ 93 V(CODE_MOVING_GC, "code-moving-gc") \ 94 V(SHARED_FUNC_MOVE_EVENT, "sfi-move") \ 95 V(SNAPSHOT_POSITION_EVENT, "snapshot-pos") \ 96 V(SNAPSHOT_CODE_NAME_EVENT, "snapshot-code-name") \ 97 V(TICK_EVENT, "tick") \ 98 V(REPEAT_META_EVENT, "repeat") \ 99 V(BUILTIN_TAG, "Builtin") \ 100 V(CALL_DEBUG_BREAK_TAG, "CallDebugBreak") \ 101 V(CALL_DEBUG_PREPARE_STEP_IN_TAG, "CallDebugPrepareStepIn") \ 102 V(CALL_IC_TAG, "CallIC") \ 103 V(CALL_INITIALIZE_TAG, "CallInitialize") \ 104 V(CALL_MEGAMORPHIC_TAG, "CallMegamorphic") \ 105 V(CALL_MISS_TAG, "CallMiss") \ 106 V(CALL_NORMAL_TAG, "CallNormal") \ 107 V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic") \ 108 V(KEYED_CALL_DEBUG_BREAK_TAG, "KeyedCallDebugBreak") \ 109 V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG, \ 110 "KeyedCallDebugPrepareStepIn") \ 111 V(KEYED_CALL_IC_TAG, "KeyedCallIC") \ 112 V(KEYED_CALL_INITIALIZE_TAG, "KeyedCallInitialize") \ 113 V(KEYED_CALL_MEGAMORPHIC_TAG, "KeyedCallMegamorphic") \ 114 V(KEYED_CALL_MISS_TAG, "KeyedCallMiss") \ 115 V(KEYED_CALL_NORMAL_TAG, "KeyedCallNormal") \ 116 V(KEYED_CALL_PRE_MONOMORPHIC_TAG, "KeyedCallPreMonomorphic") \ 117 V(CALLBACK_TAG, "Callback") \ 118 V(EVAL_TAG, "Eval") \ 119 V(FUNCTION_TAG, "Function") \ 120 V(KEYED_LOAD_IC_TAG, "KeyedLoadIC") \ 121 V(KEYED_LOAD_MEGAMORPHIC_IC_TAG, "KeyedLoadMegamorphicIC") \ 122 V(KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG, "KeyedExternalArrayLoadIC") \ 123 V(KEYED_STORE_IC_TAG, "KeyedStoreIC") \ 124 V(KEYED_STORE_MEGAMORPHIC_IC_TAG, "KeyedStoreMegamorphicIC") \ 125 V(KEYED_EXTERNAL_ARRAY_STORE_IC_TAG, "KeyedExternalArrayStoreIC") \ 126 V(LAZY_COMPILE_TAG, "LazyCompile") \ 127 V(LOAD_IC_TAG, "LoadIC") \ 128 V(REG_EXP_TAG, "RegExp") \ 129 V(SCRIPT_TAG, "Script") \ 130 V(STORE_IC_TAG, "StoreIC") \ 131 V(STUB_TAG, "Stub") \ 132 V(NATIVE_FUNCTION_TAG, "Function") \ 133 V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile") \ 134 V(NATIVE_SCRIPT_TAG, "Script") 135 // Note that 'NATIVE_' cases for functions and scripts are mapped onto 136 // original tags when writing to the log. 137 138 139 class Sampler; 140 141 142 class Logger { 143 public: 144 #define DECLARE_ENUM(enum_item, ignore) enum_item, 145 enum LogEventsAndTags { 146 LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM) 147 NUMBER_OF_LOG_EVENTS 148 }; 149 #undef DECLARE_ENUM 150 151 // Acquires resources for logging if the right flags are set. 152 bool SetUp(); 153 154 void EnsureTickerStarted(); 155 void EnsureTickerStopped(); 156 157 Sampler* sampler(); 158 159 // Frees resources acquired in SetUp. 160 // When a temporary file is used for the log, returns its stream descriptor, 161 // leaving the file open. 162 FILE* TearDown(); 163 164 // Enable the computation of a sliding window of states. 165 void EnableSlidingStateWindow(); 166 167 // Emits an event with a string value -> (name, value). 168 void StringEvent(const char* name, const char* value); 169 170 // Emits an event with an int value -> (name, value). 171 void IntEvent(const char* name, int value); 172 void IntPtrTEvent(const char* name, intptr_t value); 173 174 // Emits an event with an handle value -> (name, location). 175 void HandleEvent(const char* name, Object** location); 176 177 // Emits memory management events for C allocated structures. 178 void NewEvent(const char* name, void* object, size_t size); 179 void DeleteEvent(const char* name, void* object); 180 181 // Static versions of the above, operate on current isolate's logger. 182 // Used in TRACK_MEMORY(TypeName) defined in globals.h 183 static void NewEventStatic(const char* name, void* object, size_t size); 184 static void DeleteEventStatic(const char* name, void* object); 185 186 // Emits an event with a tag, and some resource usage information. 187 // -> (name, tag, <rusage information>). 188 // Currently, the resource usage information is a process time stamp 189 // and a real time timestamp. 190 void ResourceEvent(const char* name, const char* tag); 191 192 // Emits an event that an undefined property was read from an 193 // object. 194 void SuspectReadEvent(String* name, Object* obj); 195 196 // Emits an event when a message is put on or read from a debugging queue. 197 // DebugTag lets us put a call-site specific label on the event. 198 void DebugTag(const char* call_site_tag); 199 void DebugEvent(const char* event_type, Vector<uint16_t> parameter); 200 201 202 // ==== Events logged by --log-api. ==== 203 void ApiNamedSecurityCheck(Object* key); 204 void ApiIndexedSecurityCheck(uint32_t index); 205 void ApiNamedPropertyAccess(const char* tag, JSObject* holder, Object* name); 206 void ApiIndexedPropertyAccess(const char* tag, 207 JSObject* holder, 208 uint32_t index); 209 void ApiObjectAccess(const char* tag, JSObject* obj); 210 void ApiEntryCall(const char* name); 211 212 213 // ==== Events logged by --log-code. ==== 214 // Emits a code event for a callback function. 215 void CallbackEvent(String* name, Address entry_point); 216 void GetterCallbackEvent(String* name, Address entry_point); 217 void SetterCallbackEvent(String* name, Address entry_point); 218 // Emits a code create event. 219 void CodeCreateEvent(LogEventsAndTags tag, 220 Code* code, const char* source); 221 void CodeCreateEvent(LogEventsAndTags tag, 222 Code* code, String* name); 223 void CodeCreateEvent(LogEventsAndTags tag, 224 Code* code, 225 SharedFunctionInfo* shared, 226 String* name); 227 void CodeCreateEvent(LogEventsAndTags tag, 228 Code* code, 229 SharedFunctionInfo* shared, 230 String* source, int line); 231 void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count); 232 void CodeMovingGCEvent(); 233 // Emits a code create event for a RegExp. 234 void RegExpCodeCreateEvent(Code* code, String* source); 235 // Emits a code move event. 236 void CodeMoveEvent(Address from, Address to); 237 // Emits a code delete event. 238 void CodeDeleteEvent(Address from); 239 240 void SharedFunctionInfoMoveEvent(Address from, Address to); 241 242 void SnapshotPositionEvent(Address addr, int pos); 243 244 // ==== Events logged by --log-gc. ==== 245 // Heap sampling events: start, end, and individual types. 246 void HeapSampleBeginEvent(const char* space, const char* kind); 247 void HeapSampleEndEvent(const char* space, const char* kind); 248 void HeapSampleItemEvent(const char* type, int number, int bytes); 249 void HeapSampleJSConstructorEvent(const char* constructor, 250 int number, int bytes); 251 void HeapSampleJSRetainersEvent(const char* constructor, 252 const char* event); 253 void HeapSampleJSProducerEvent(const char* constructor, 254 Address* stack); 255 void HeapSampleStats(const char* space, const char* kind, 256 intptr_t capacity, intptr_t used); 257 258 void SharedLibraryEvent(const char* library_path, 259 uintptr_t start, 260 uintptr_t end); 261 void SharedLibraryEvent(const wchar_t* library_path, 262 uintptr_t start, 263 uintptr_t end); 264 265 // ==== Events logged by --log-regexp ==== 266 // Regexp compilation and execution events. 267 268 void RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache); 269 270 // Log an event reported from generated code 271 void LogRuntime(Vector<const char> format, JSArray* args); 272 is_logging()273 bool is_logging() { 274 return logging_nesting_ > 0; 275 } 276 277 // Pause/Resume collection of profiling data. 278 // When data collection is paused, CPU Tick events are discarded until 279 // data collection is Resumed. 280 void PauseProfiler(); 281 void ResumeProfiler(); 282 bool IsProfilerPaused(); 283 284 void LogExistingFunction(Handle<SharedFunctionInfo> shared, 285 Handle<Code> code); 286 // Logs all compiled functions found in the heap. 287 void LogCompiledFunctions(); 288 // Logs all accessor callbacks found in the heap. 289 void LogAccessorCallbacks(); 290 // Used for logging stubs found in the snapshot. 291 void LogCodeObjects(); 292 293 // Converts tag to a corresponding NATIVE_... if the script is native. 294 INLINE(static LogEventsAndTags ToNativeByScript(LogEventsAndTags, Script*)); 295 296 // Profiler's sampling interval (in milliseconds). 297 #if defined(ANDROID) 298 // Phones and tablets have processors that are much slower than desktop 299 // and laptop computers for which current heuristics are tuned. 300 static const int kSamplingIntervalMs = 5; 301 #else 302 static const int kSamplingIntervalMs = 1; 303 #endif 304 305 // Callback from Log, stops profiling in case of insufficient resources. 306 void LogFailure(); 307 308 private: 309 class NameBuffer; 310 class NameMap; 311 312 Logger(); 313 ~Logger(); 314 315 // Emits the profiler's first message. 316 void ProfilerBeginEvent(); 317 318 // Emits callback event messages. 319 void CallbackEventInternal(const char* prefix, 320 const char* name, 321 Address entry_point); 322 323 // Internal configurable move event. 324 void MoveEventInternal(LogEventsAndTags event, Address from, Address to); 325 326 // Internal configurable move event. 327 void DeleteEventInternal(LogEventsAndTags event, Address from); 328 329 // Emits the source code of a regexp. Used by regexp events. 330 void LogRegExpSource(Handle<JSRegExp> regexp); 331 332 // Used for logging stubs found in the snapshot. 333 void LogCodeObject(Object* code_object); 334 335 // Emits general information about generated code. 336 void LogCodeInfo(); 337 338 void RegisterSnapshotCodeName(Code* code, const char* name, int name_size); 339 340 // Low-level logging support. 341 342 void LowLevelCodeCreateEvent(Code* code, const char* name, int name_size); 343 344 void LowLevelCodeMoveEvent(Address from, Address to); 345 346 void LowLevelCodeDeleteEvent(Address from); 347 348 void LowLevelSnapshotPositionEvent(Address addr, int pos); 349 350 void LowLevelLogWriteBytes(const char* bytes, int size); 351 352 template <typename T> LowLevelLogWriteStruct(const T & s)353 void LowLevelLogWriteStruct(const T& s) { 354 char tag = T::kTag; 355 LowLevelLogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag)); 356 LowLevelLogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s)); 357 } 358 359 // Emits a profiler tick event. Used by the profiler thread. 360 void TickEvent(TickSample* sample, bool overflow); 361 362 void ApiEvent(const char* name, ...); 363 364 // Logs a StringEvent regardless of whether FLAG_log is true. 365 void UncheckedStringEvent(const char* name, const char* value); 366 367 // Logs an IntEvent regardless of whether FLAG_log is true. 368 void UncheckedIntEvent(const char* name, int value); 369 void UncheckedIntPtrTEvent(const char* name, intptr_t value); 370 371 // Returns whether profiler's sampler is active. 372 bool IsProfilerSamplerActive(); 373 374 // The sampler used by the profiler and the sliding state window. 375 Ticker* ticker_; 376 377 // When the statistical profile is active, profiler_ 378 // points to a Profiler, that handles collection 379 // of samples. 380 Profiler* profiler_; 381 382 // SlidingStateWindow instance keeping a sliding window of the most 383 // recent VM states. 384 SlidingStateWindow* sliding_state_window_; 385 386 // An array of log events names. 387 const char* const* log_events_; 388 389 // Internal implementation classes with access to 390 // private members. 391 friend class EventLog; 392 friend class Isolate; 393 friend class LogMessageBuilder; 394 friend class TimeLog; 395 friend class Profiler; 396 friend class SlidingStateWindow; 397 friend class StackTracer; 398 friend class VMState; 399 400 friend class LoggerTestHelper; 401 402 403 int logging_nesting_; 404 int cpu_profiler_nesting_; 405 406 Log* log_; 407 408 NameBuffer* name_buffer_; 409 410 NameMap* address_to_name_map_; 411 412 // Guards against multiple calls to TearDown() that can happen in some tests. 413 // 'true' between SetUp() and TearDown(). 414 bool is_initialized_; 415 416 // Support for 'incremental addresses' in compressed logs: 417 // LogMessageBuilder::AppendAddress(Address addr) 418 Address last_address_; 419 // Logger::TickEvent(...) 420 Address prev_sp_; 421 Address prev_function_; 422 // Logger::MoveEventInternal(...) 423 Address prev_to_; 424 // Logger::FunctionCreateEvent(...) 425 Address prev_code_; 426 427 friend class CpuProfiler; 428 }; 429 430 431 // Process wide registry of samplers. 432 class SamplerRegistry : public AllStatic { 433 public: 434 enum State { 435 HAS_NO_SAMPLERS, 436 HAS_SAMPLERS, 437 HAS_CPU_PROFILING_SAMPLERS 438 }; 439 440 typedef void (*VisitSampler)(Sampler*, void*); 441 442 static State GetState(); 443 444 // Iterates over all active samplers keeping the internal lock held. 445 // Returns whether there are any active samplers. 446 static bool IterateActiveSamplers(VisitSampler func, void* param); 447 448 // Adds/Removes an active sampler. 449 static void AddActiveSampler(Sampler* sampler); 450 static void RemoveActiveSampler(Sampler* sampler); 451 452 private: ActiveSamplersExist()453 static bool ActiveSamplersExist() { 454 return active_samplers_ != NULL && !active_samplers_->is_empty(); 455 } 456 457 static List<Sampler*>* active_samplers_; 458 459 DISALLOW_IMPLICIT_CONSTRUCTORS(SamplerRegistry); 460 }; 461 462 463 // Class that extracts stack trace, used for profiling. 464 class StackTracer : public AllStatic { 465 public: 466 static void Trace(Isolate* isolate, TickSample* sample); 467 }; 468 469 } } // namespace v8::internal 470 471 472 #endif // V8_LOG_H_ 473