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