Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_LOG_H_
      6 #define V8_LOG_H_
      7 
      8 #include <string>
      9 
     10 #include "src/allocation.h"
     11 #include "src/base/compiler-specific.h"
     12 #include "src/base/platform/elapsed-timer.h"
     13 #include "src/base/platform/platform.h"
     14 #include "src/code-events.h"
     15 #include "src/isolate.h"
     16 #include "src/objects.h"
     17 
     18 namespace v8 {
     19 
     20 struct TickSample;
     21 
     22 namespace sampler {
     23 class Sampler;
     24 }
     25 
     26 namespace internal {
     27 
     28 // Logger is used for collecting logging information from V8 during
     29 // execution. The result is dumped to a file.
     30 //
     31 // Available command line flags:
     32 //
     33 //  --log
     34 // Minimal logging (no API, code, or GC sample events), default is off.
     35 //
     36 // --log-all
     37 // Log all events to the file, default is off.  This is the same as combining
     38 // --log-api, --log-code, --log-gc, and --log-regexp.
     39 //
     40 // --log-api
     41 // Log API events to the logfile, default is off.  --log-api implies --log.
     42 //
     43 // --log-code
     44 // Log code (create, move, and delete) events to the logfile, default is off.
     45 // --log-code implies --log.
     46 //
     47 // --log-gc
     48 // Log GC heap samples after each GC that can be processed by hp2ps, default
     49 // is off.  --log-gc implies --log.
     50 //
     51 // --log-regexp
     52 // Log creation and use of regular expressions, Default is off.
     53 // --log-regexp implies --log.
     54 //
     55 // --logfile <filename>
     56 // Specify the name of the logfile, default is "v8.log".
     57 //
     58 // --prof
     59 // Collect statistical profiling information (ticks), default is off.  The
     60 // tick profiler requires code events, so --prof implies --log-code.
     61 
     62 // Forward declarations.
     63 class CodeEventListener;
     64 class CpuProfiler;
     65 class Isolate;
     66 class JitLogger;
     67 class Log;
     68 class LowLevelLogger;
     69 class PerfBasicLogger;
     70 class PerfJitLogger;
     71 class Profiler;
     72 class ProfilerListener;
     73 class RuntimeCallTimer;
     74 class Ticker;
     75 
     76 #undef LOG
     77 #define LOG(isolate, Call)                              \
     78   do {                                                  \
     79     v8::internal::Logger* logger = (isolate)->logger(); \
     80     if (logger->is_logging()) logger->Call;             \
     81   } while (false)
     82 
     83 #define LOG_CODE_EVENT(isolate, Call)                   \
     84   do {                                                  \
     85     v8::internal::Logger* logger = (isolate)->logger(); \
     86     if (logger->is_logging_code_events()) logger->Call; \
     87   } while (false)
     88 
     89 class Logger : public CodeEventListener {
     90  public:
     91   enum StartEnd { START = 0, END = 1 };
     92 
     93   // Acquires resources for logging if the right flags are set.
     94   bool SetUp(Isolate* isolate);
     95 
     96   // Sets the current code event handler.
     97   void SetCodeEventHandler(uint32_t options,
     98                            JitCodeEventHandler event_handler);
     99 
    100   // Sets up ProfilerListener.
    101   void SetUpProfilerListener();
    102 
    103   // Tear down ProfilerListener if it has no observers.
    104   void TearDownProfilerListener();
    105 
    106   sampler::Sampler* sampler();
    107 
    108   ProfilerListener* profiler_listener() { return profiler_listener_.get(); }
    109 
    110   // Frees resources acquired in SetUp.
    111   // When a temporary file is used for the log, returns its stream descriptor,
    112   // leaving the file open.
    113   FILE* TearDown();
    114 
    115   // Emits an event with a string value -> (name, value).
    116   void StringEvent(const char* name, const char* value);
    117 
    118   // Emits an event with an int value -> (name, value).
    119   void IntEvent(const char* name, int value);
    120   void IntPtrTEvent(const char* name, intptr_t value);
    121 
    122   // Emits an event with an handle value -> (name, location).
    123   void HandleEvent(const char* name, Object** location);
    124 
    125   // Emits memory management events for C allocated structures.
    126   void NewEvent(const char* name, void* object, size_t size);
    127   void DeleteEvent(const char* name, void* object);
    128 
    129   // Emits an event with a tag, and some resource usage information.
    130   // -> (name, tag, <rusage information>).
    131   // Currently, the resource usage information is a process time stamp
    132   // and a real time timestamp.
    133   void ResourceEvent(const char* name, const char* tag);
    134 
    135   // Emits an event that an undefined property was read from an
    136   // object.
    137   void SuspectReadEvent(Name* name, Object* obj);
    138 
    139   // ==== Events logged by --log-api. ====
    140   void ApiSecurityCheck();
    141   void ApiNamedPropertyAccess(const char* tag, JSObject* holder, Object* name);
    142   void ApiIndexedPropertyAccess(const char* tag,
    143                                 JSObject* holder,
    144                                 uint32_t index);
    145   void ApiObjectAccess(const char* tag, JSObject* obj);
    146   void ApiEntryCall(const char* name);
    147 
    148   // ==== Events logged by --log-code. ====
    149   void addCodeEventListener(CodeEventListener* listener);
    150   void removeCodeEventListener(CodeEventListener* listener);
    151 
    152   // Emits a code event for a callback function.
    153   void CallbackEvent(Name* name, Address entry_point);
    154   void GetterCallbackEvent(Name* name, Address entry_point);
    155   void SetterCallbackEvent(Name* name, Address entry_point);
    156   // Emits a code create event.
    157   void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
    158                        AbstractCode* code, const char* source);
    159   void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
    160                        AbstractCode* code, Name* name);
    161   void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
    162                        AbstractCode* code, SharedFunctionInfo* shared,
    163                        Name* name);
    164   void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
    165                        AbstractCode* code, SharedFunctionInfo* shared,
    166                        Name* source, int line, int column);
    167   void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
    168                        AbstractCode* code, int args_count);
    169   // Emits a code deoptimization event.
    170   void CodeDisableOptEvent(AbstractCode* code, SharedFunctionInfo* shared);
    171   void CodeMovingGCEvent();
    172   // Emits a code create event for a RegExp.
    173   void RegExpCodeCreateEvent(AbstractCode* code, String* source);
    174   // Emits a code move event.
    175   void CodeMoveEvent(AbstractCode* from, Address to);
    176   // Emits a code line info record event.
    177   void CodeLinePosInfoRecordEvent(AbstractCode* code,
    178                                   ByteArray* source_position_table);
    179 
    180   void SharedFunctionInfoMoveEvent(Address from, Address to);
    181 
    182   void CodeNameEvent(Address addr, int pos, const char* code_name);
    183 
    184   void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta);
    185 
    186   void ICEvent(const char* type, bool keyed, const Address pc, int line,
    187                int column, Map* map, Object* key, char old_state,
    188                char new_state, const char* modifier,
    189                const char* slow_stub_reason);
    190   void CompareIC(const Address pc, int line, int column, Code* stub,
    191                  const char* op, const char* old_left, const char* old_right,
    192                  const char* old_state, const char* new_left,
    193                  const char* new_right, const char* new_state);
    194   void BinaryOpIC(const Address pc, int line, int column, Code* stub,
    195                   const char* old_state, const char* new_state,
    196                   AllocationSite* allocation_site);
    197   void ToBooleanIC(const Address pc, int line, int column, Code* stub,
    198                    const char* old_state, const char* new_state);
    199   void PatchIC(const Address pc, const Address test, int delta);
    200 
    201   // ==== Events logged by --log-gc. ====
    202   // Heap sampling events: start, end, and individual types.
    203   void HeapSampleBeginEvent(const char* space, const char* kind);
    204   void HeapSampleEndEvent(const char* space, const char* kind);
    205   void HeapSampleItemEvent(const char* type, int number, int bytes);
    206   void HeapSampleJSConstructorEvent(const char* constructor,
    207                                     int number, int bytes);
    208   void HeapSampleJSRetainersEvent(const char* constructor,
    209                                          const char* event);
    210   void HeapSampleJSProducerEvent(const char* constructor,
    211                                  Address* stack);
    212   void HeapSampleStats(const char* space, const char* kind,
    213                        intptr_t capacity, intptr_t used);
    214 
    215   void SharedLibraryEvent(const std::string& library_path, uintptr_t start,
    216                           uintptr_t end, intptr_t aslr_slide);
    217 
    218   void CurrentTimeEvent();
    219 
    220   void TimerEvent(StartEnd se, const char* name);
    221 
    222   static void EnterExternal(Isolate* isolate);
    223   static void LeaveExternal(Isolate* isolate);
    224 
    225   static void DefaultEventLoggerSentinel(const char* name, int event) {}
    226 
    227   INLINE(static void CallEventLogger(Isolate* isolate, const char* name,
    228                                      StartEnd se, bool expose_to_api));
    229 
    230   bool is_logging() {
    231     return is_logging_;
    232   }
    233 
    234   bool is_logging_code_events() {
    235     return is_logging() || jit_logger_ != NULL;
    236   }
    237 
    238   // Stop collection of profiling data.
    239   // When data collection is paused, CPU Tick events are discarded.
    240   void StopProfiler();
    241 
    242   void LogExistingFunction(Handle<SharedFunctionInfo> shared,
    243                            Handle<AbstractCode> code);
    244   // Logs all compiled functions found in the heap.
    245   void LogCompiledFunctions();
    246   // Logs all accessor callbacks found in the heap.
    247   void LogAccessorCallbacks();
    248   // Used for logging stubs found in the snapshot.
    249   void LogCodeObjects();
    250   // Used for logging bytecode handlers found in the snapshot.
    251   void LogBytecodeHandlers();
    252 
    253   // Converts tag to a corresponding NATIVE_... if the script is native.
    254   INLINE(static CodeEventListener::LogEventsAndTags ToNativeByScript(
    255       CodeEventListener::LogEventsAndTags, Script*));
    256 
    257   // Profiler's sampling interval (in milliseconds).
    258 #if defined(ANDROID)
    259   // Phones and tablets have processors that are much slower than desktop
    260   // and laptop computers for which current heuristics are tuned.
    261   static const int kSamplingIntervalMs = 5;
    262 #else
    263   static const int kSamplingIntervalMs = 1;
    264 #endif
    265 
    266   // Callback from Log, stops profiling in case of insufficient resources.
    267   void LogFailure();
    268 
    269  private:
    270   explicit Logger(Isolate* isolate);
    271   ~Logger();
    272 
    273   // Emits the profiler's first message.
    274   void ProfilerBeginEvent();
    275 
    276   // Emits callback event messages.
    277   void CallbackEventInternal(const char* prefix,
    278                              Name* name,
    279                              Address entry_point);
    280 
    281   // Internal configurable move event.
    282   void MoveEventInternal(CodeEventListener::LogEventsAndTags event,
    283                          Address from, Address to);
    284 
    285   // Used for logging stubs found in the snapshot.
    286   void LogCodeObject(Object* code_object);
    287 
    288   // Helper method. It resets name_buffer_ and add tag name into it.
    289   void InitNameBuffer(CodeEventListener::LogEventsAndTags tag);
    290 
    291   // Emits a profiler tick event. Used by the profiler thread.
    292   void TickEvent(TickSample* sample, bool overflow);
    293   void RuntimeCallTimerEvent();
    294 
    295   PRINTF_FORMAT(2, 3) void ApiEvent(const char* format, ...);
    296 
    297   // Logs a StringEvent regardless of whether FLAG_log is true.
    298   void UncheckedStringEvent(const char* name, const char* value);
    299 
    300   // Logs an IntEvent regardless of whether FLAG_log is true.
    301   void UncheckedIntEvent(const char* name, int value);
    302   void UncheckedIntPtrTEvent(const char* name, intptr_t value);
    303 
    304   Isolate* isolate_;
    305 
    306   // The sampler used by the profiler and the sliding state window.
    307   Ticker* ticker_;
    308 
    309   // When the statistical profile is active, profiler_
    310   // points to a Profiler, that handles collection
    311   // of samples.
    312   Profiler* profiler_;
    313 
    314   // An array of log events names.
    315   const char* const* log_events_;
    316 
    317   // Internal implementation classes with access to
    318   // private members.
    319   friend class EventLog;
    320   friend class Isolate;
    321   friend class TimeLog;
    322   friend class Profiler;
    323   template <StateTag Tag> friend class VMState;
    324   friend class LoggerTestHelper;
    325 
    326   bool is_logging_;
    327   Log* log_;
    328   PerfBasicLogger* perf_basic_logger_;
    329   PerfJitLogger* perf_jit_logger_;
    330   LowLevelLogger* ll_logger_;
    331   JitLogger* jit_logger_;
    332   std::unique_ptr<ProfilerListener> profiler_listener_;
    333   List<CodeEventListener*> listeners_;
    334 
    335   // Guards against multiple calls to TearDown() that can happen in some tests.
    336   // 'true' between SetUp() and TearDown().
    337   bool is_initialized_;
    338 
    339   base::ElapsedTimer timer_;
    340 
    341   friend class CpuProfiler;
    342 };
    343 
    344 #define TIMER_EVENTS_LIST(V)    \
    345   V(RecompileSynchronous, true) \
    346   V(RecompileConcurrent, true)  \
    347   V(CompileIgnition, true)      \
    348   V(CompileFullCode, true)      \
    349   V(OptimizeCode, true)         \
    350   V(CompileCode, true)          \
    351   V(DeoptimizeCode, true)       \
    352   V(Execute, true)              \
    353   V(External, true)
    354 
    355 #define V(TimerName, expose)                                                  \
    356   class TimerEvent##TimerName : public AllStatic {                            \
    357    public:                                                                    \
    358     static const char* name(void* unused = NULL) { return "V8." #TimerName; } \
    359     static bool expose_to_api() { return expose; }                            \
    360   };
    361 TIMER_EVENTS_LIST(V)
    362 #undef V
    363 
    364 
    365 template <class TimerEvent>
    366 class TimerEventScope {
    367  public:
    368   explicit TimerEventScope(Isolate* isolate) : isolate_(isolate) {
    369     LogTimerEvent(Logger::START);
    370   }
    371 
    372   ~TimerEventScope() { LogTimerEvent(Logger::END); }
    373 
    374  private:
    375   void LogTimerEvent(Logger::StartEnd se);
    376   Isolate* isolate_;
    377 };
    378 
    379 class CodeEventLogger : public CodeEventListener {
    380  public:
    381   CodeEventLogger();
    382   ~CodeEventLogger() override;
    383 
    384   void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
    385                        const char* comment) override;
    386   void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
    387                        Name* name) override;
    388   void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
    389                        int args_count) override;
    390   void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
    391                        SharedFunctionInfo* shared, Name* name) override;
    392   void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
    393                        SharedFunctionInfo* shared, Name* source, int line,
    394                        int column) override;
    395   void RegExpCodeCreateEvent(AbstractCode* code, String* source) override;
    396 
    397   void CallbackEvent(Name* name, Address entry_point) override {}
    398   void GetterCallbackEvent(Name* name, Address entry_point) override {}
    399   void SetterCallbackEvent(Name* name, Address entry_point) override {}
    400   void SharedFunctionInfoMoveEvent(Address from, Address to) override {}
    401   void CodeMovingGCEvent() override {}
    402   void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) override {}
    403 
    404  private:
    405   class NameBuffer;
    406 
    407   virtual void LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo* shared,
    408                                  const char* name, int length) = 0;
    409 
    410   NameBuffer* name_buffer_;
    411 };
    412 
    413 
    414 }  // namespace internal
    415 }  // namespace v8
    416 
    417 
    418 #endif  // V8_LOG_H_
    419