Home | History | Annotate | Download | only in src
      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