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