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 class CompressionHelper; 78 79 #undef LOG 80 #ifdef ENABLE_LOGGING_AND_PROFILING 81 #define LOG(Call) \ 82 do { \ 83 if (v8::internal::Logger::is_logging()) \ 84 v8::internal::Logger::Call; \ 85 } while (false) 86 #else 87 #define LOG(Call) ((void) 0) 88 #endif 89 90 91 class VMState BASE_EMBEDDED { 92 #ifdef ENABLE_LOGGING_AND_PROFILING 93 public: 94 inline VMState(StateTag state); 95 inline ~VMState(); 96 state()97 StateTag state() { return state_; } external_callback()98 Address external_callback() { return external_callback_; } set_external_callback(Address external_callback)99 void set_external_callback(Address external_callback) { 100 external_callback_ = external_callback; 101 } 102 103 private: 104 bool disabled_; 105 StateTag state_; 106 VMState* previous_; 107 Address external_callback_; 108 #else 109 public: 110 explicit VMState(StateTag state) {} 111 #endif 112 }; 113 114 115 #define LOG_EVENTS_AND_TAGS_LIST(V) \ 116 V(CODE_CREATION_EVENT, "code-creation", "cc") \ 117 V(CODE_MOVE_EVENT, "code-move", "cm") \ 118 V(CODE_DELETE_EVENT, "code-delete", "cd") \ 119 V(FUNCTION_CREATION_EVENT, "function-creation", "fc") \ 120 V(FUNCTION_MOVE_EVENT, "function-move", "fm") \ 121 V(FUNCTION_DELETE_EVENT, "function-delete", "fd") \ 122 V(SNAPSHOT_POSITION_EVENT, "snapshot-pos", "sp") \ 123 V(TICK_EVENT, "tick", "t") \ 124 V(REPEAT_META_EVENT, "repeat", "r") \ 125 V(BUILTIN_TAG, "Builtin", "bi") \ 126 V(CALL_DEBUG_BREAK_TAG, "CallDebugBreak", "cdb") \ 127 V(CALL_DEBUG_PREPARE_STEP_IN_TAG, "CallDebugPrepareStepIn", "cdbsi") \ 128 V(CALL_IC_TAG, "CallIC", "cic") \ 129 V(CALL_INITIALIZE_TAG, "CallInitialize", "ci") \ 130 V(CALL_MEGAMORPHIC_TAG, "CallMegamorphic", "cmm") \ 131 V(CALL_MISS_TAG, "CallMiss", "cm") \ 132 V(CALL_NORMAL_TAG, "CallNormal", "cn") \ 133 V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic", "cpm") \ 134 V(CALLBACK_TAG, "Callback", "cb") \ 135 V(EVAL_TAG, "Eval", "e") \ 136 V(FUNCTION_TAG, "Function", "f") \ 137 V(KEYED_LOAD_IC_TAG, "KeyedLoadIC", "klic") \ 138 V(KEYED_STORE_IC_TAG, "KeyedStoreIC", "ksic") \ 139 V(LAZY_COMPILE_TAG, "LazyCompile", "lc") \ 140 V(LOAD_IC_TAG, "LoadIC", "lic") \ 141 V(REG_EXP_TAG, "RegExp", "re") \ 142 V(SCRIPT_TAG, "Script", "sc") \ 143 V(STORE_IC_TAG, "StoreIC", "sic") \ 144 V(STUB_TAG, "Stub", "s") 145 146 class Logger { 147 public: 148 #define DECLARE_ENUM(enum_item, ignore1, ignore2) enum_item, 149 enum LogEventsAndTags { 150 LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM) 151 NUMBER_OF_LOG_EVENTS 152 }; 153 #undef DECLARE_ENUM 154 155 // Acquires resources for logging if the right flags are set. 156 static bool Setup(); 157 158 // Frees resources acquired in Setup. 159 static void TearDown(); 160 161 // Enable the computation of a sliding window of states. 162 static void EnableSlidingStateWindow(); 163 164 // Emits an event with a string value -> (name, value). 165 static void StringEvent(const char* name, const char* value); 166 167 // Emits an event with an int value -> (name, value). 168 static void IntEvent(const char* name, int value); 169 170 // Emits an event with an handle value -> (name, location). 171 static void HandleEvent(const char* name, Object** location); 172 173 // Emits memory management events for C allocated structures. 174 static void NewEvent(const char* name, void* object, size_t size); 175 static void DeleteEvent(const char* name, void* object); 176 177 // Emits an event with a tag, and some resource usage information. 178 // -> (name, tag, <rusage information>). 179 // Currently, the resource usage information is a process time stamp 180 // and a real time timestamp. 181 static void ResourceEvent(const char* name, const char* tag); 182 183 // Emits an event that an undefined property was read from an 184 // object. 185 static void SuspectReadEvent(String* name, Object* obj); 186 187 // Emits an event when a message is put on or read from a debugging queue. 188 // DebugTag lets us put a call-site specific label on the event. 189 static void DebugTag(const char* call_site_tag); 190 static void DebugEvent(const char* event_type, Vector<uint16_t> parameter); 191 192 193 // ==== Events logged by --log-api. ==== 194 static void ApiNamedSecurityCheck(Object* key); 195 static void ApiIndexedSecurityCheck(uint32_t index); 196 static void ApiNamedPropertyAccess(const char* tag, 197 JSObject* holder, 198 Object* name); 199 static void ApiIndexedPropertyAccess(const char* tag, 200 JSObject* holder, 201 uint32_t index); 202 static void ApiObjectAccess(const char* tag, JSObject* obj); 203 static void ApiEntryCall(const char* name); 204 205 206 // ==== Events logged by --log-code. ==== 207 // Emits a code event for a callback function. 208 static void CallbackEvent(String* name, Address entry_point); 209 static void GetterCallbackEvent(String* name, Address entry_point); 210 static void SetterCallbackEvent(String* name, Address entry_point); 211 // Emits a code create event. 212 static void CodeCreateEvent(LogEventsAndTags tag, 213 Code* code, const char* source); 214 static void CodeCreateEvent(LogEventsAndTags tag, Code* code, String* name); 215 static void CodeCreateEvent(LogEventsAndTags tag, Code* code, String* name, 216 String* source, int line); 217 static void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count); 218 // Emits a code create event for a RegExp. 219 static void RegExpCodeCreateEvent(Code* code, String* source); 220 // Emits a code move event. 221 static void CodeMoveEvent(Address from, Address to); 222 // Emits a code delete event. 223 static void CodeDeleteEvent(Address from); 224 // Emits a function object create event. 225 static void FunctionCreateEvent(JSFunction* function); 226 // Emits a function move event. 227 static void FunctionMoveEvent(Address from, Address to); 228 // Emits a function delete event. 229 static void FunctionDeleteEvent(Address from); 230 231 static void SnapshotPositionEvent(Address addr, int pos); 232 233 // ==== Events logged by --log-gc. ==== 234 // Heap sampling events: start, end, and individual types. 235 static void HeapSampleBeginEvent(const char* space, const char* kind); 236 static void HeapSampleEndEvent(const char* space, const char* kind); 237 static void HeapSampleItemEvent(const char* type, int number, int bytes); 238 static void HeapSampleJSConstructorEvent(const char* constructor, 239 int number, int bytes); 240 static void HeapSampleJSRetainersEvent(const char* constructor, 241 const char* event); 242 static void HeapSampleJSProducerEvent(const char* constructor, 243 Address* stack); 244 static void HeapSampleStats(const char* space, const char* kind, 245 int capacity, int used); 246 247 static void SharedLibraryEvent(const char* library_path, 248 uintptr_t start, 249 uintptr_t end); 250 static void SharedLibraryEvent(const wchar_t* library_path, 251 uintptr_t start, 252 uintptr_t end); 253 254 // ==== Events logged by --log-regexp ==== 255 // Regexp compilation and execution events. 256 257 static void RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache); 258 259 // Log an event reported from generated code 260 static void LogRuntime(Vector<const char> format, JSArray* args); 261 262 #ifdef ENABLE_LOGGING_AND_PROFILING state()263 static StateTag state() { 264 return current_state_ ? current_state_->state() : OTHER; 265 } 266 is_logging()267 static bool is_logging() { 268 return is_logging_; 269 } 270 271 // Pause/Resume collection of profiling data. 272 // When data collection is paused, CPU Tick events are discarded until 273 // data collection is Resumed. 274 static void PauseProfiler(int flags, int tag); 275 static void ResumeProfiler(int flags, int tag); 276 static int GetActiveProfilerModules(); 277 278 // If logging is performed into a memory buffer, allows to 279 // retrieve previously written messages. See v8.h. 280 static int GetLogLines(int from_pos, char* dest_buf, int max_size); 281 282 // Logs all compiled functions found in the heap. 283 static void LogCompiledFunctions(); 284 // Logs all compiled JSFunction objects found in the heap. 285 static void LogFunctionObjects(); 286 // Logs all accessor callbacks found in the heap. 287 static void LogAccessorCallbacks(); 288 // Used for logging stubs found in the snapshot. 289 static void LogCodeObjects(); 290 291 private: 292 293 // Profiler's sampling interval (in milliseconds). 294 static const int kSamplingIntervalMs = 1; 295 296 // Size of window used for log records compression. 297 static const int kCompressionWindowSize = 4; 298 299 // Emits the profiler's first message. 300 static void ProfilerBeginEvent(); 301 302 // Emits callback event messages. 303 static void CallbackEventInternal(const char* prefix, 304 const char* name, 305 Address entry_point); 306 307 // Internal configurable move event. 308 static void MoveEventInternal(LogEventsAndTags event, 309 Address from, 310 Address to); 311 312 // Internal configurable move event. 313 static void DeleteEventInternal(LogEventsAndTags event, 314 Address from); 315 316 // Emits aliases for compressed messages. 317 static void LogAliases(); 318 319 // Emits the source code of a regexp. Used by regexp events. 320 static void LogRegExpSource(Handle<JSRegExp> regexp); 321 322 // Used for logging stubs found in the snapshot. 323 static void LogCodeObject(Object* code_object); 324 325 // Emits a profiler tick event. Used by the profiler thread. 326 static void TickEvent(TickSample* sample, bool overflow); 327 328 static void ApiEvent(const char* name, ...); 329 330 // Logs a StringEvent regardless of whether FLAG_log is true. 331 static void UncheckedStringEvent(const char* name, const char* value); 332 333 // Stops logging and profiling in case of insufficient resources. 334 static void StopLoggingAndProfiling(); 335 336 // Returns whether profiler's sampler is active. 337 static bool IsProfilerSamplerActive(); 338 339 // The sampler used by the profiler and the sliding state window. 340 static Ticker* ticker_; 341 342 // When the statistical profile is active, profiler_ 343 // points to a Profiler, that handles collection 344 // of samples. 345 static Profiler* profiler_; 346 347 // A stack of VM states. 348 static VMState* current_state_; 349 350 // Singleton bottom or default vm state. 351 static VMState bottom_state_; 352 353 // SlidingStateWindow instance keeping a sliding window of the most 354 // recent VM states. 355 static SlidingStateWindow* sliding_state_window_; 356 357 // An array of log events names. 358 static const char** log_events_; 359 360 // An instance of helper created if log compression is enabled. 361 static CompressionHelper* compression_helper_; 362 363 // Internal implementation classes with access to 364 // private members. 365 friend class CompressionHelper; 366 friend class EventLog; 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 static bool is_logging_; 376 static int cpu_profiler_nesting_; 377 static int heap_profiler_nesting_; 378 #else is_logging()379 static bool is_logging() { return false; } 380 #endif 381 }; 382 383 384 // Class that extracts stack trace, used for profiling. 385 class StackTracer : public AllStatic { 386 public: 387 static void Trace(TickSample* sample); 388 }; 389 390 391 } } // namespace v8::internal 392 393 #endif // V8_LOG_H_ 394