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