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