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_CPU_PROFILER_H_
      6 #define V8_CPU_PROFILER_H_
      7 
      8 #include "src/allocation.h"
      9 #include "src/base/atomicops.h"
     10 #include "src/base/platform/time.h"
     11 #include "src/circular-queue.h"
     12 #include "src/sampler.h"
     13 #include "src/unbound-queue.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 
     18 // Forward declarations.
     19 class CodeEntry;
     20 class CodeMap;
     21 class CompilationInfo;
     22 class CpuProfile;
     23 class CpuProfilesCollection;
     24 class ProfileGenerator;
     25 
     26 #define CODE_EVENTS_TYPE_LIST(V)                                   \
     27   V(CODE_CREATION,    CodeCreateEventRecord)                       \
     28   V(CODE_MOVE,        CodeMoveEventRecord)                         \
     29   V(CODE_DISABLE_OPT, CodeDisableOptEventRecord)                   \
     30   V(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord)           \
     31   V(REPORT_BUILTIN,   ReportBuiltinEventRecord)
     32 
     33 
     34 class CodeEventRecord {
     35  public:
     36 #define DECLARE_TYPE(type, ignore) type,
     37   enum Type {
     38     NONE = 0,
     39     CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
     40     NUMBER_OF_TYPES
     41   };
     42 #undef DECLARE_TYPE
     43 
     44   Type type;
     45   mutable unsigned order;
     46 };
     47 
     48 
     49 class CodeCreateEventRecord : public CodeEventRecord {
     50  public:
     51   Address start;
     52   CodeEntry* entry;
     53   unsigned size;
     54   Address shared;
     55 
     56   INLINE(void UpdateCodeMap(CodeMap* code_map));
     57 };
     58 
     59 
     60 class CodeMoveEventRecord : public CodeEventRecord {
     61  public:
     62   Address from;
     63   Address to;
     64 
     65   INLINE(void UpdateCodeMap(CodeMap* code_map));
     66 };
     67 
     68 
     69 class CodeDisableOptEventRecord : public CodeEventRecord {
     70  public:
     71   Address start;
     72   const char* bailout_reason;
     73 
     74   INLINE(void UpdateCodeMap(CodeMap* code_map));
     75 };
     76 
     77 
     78 class SharedFunctionInfoMoveEventRecord : public CodeEventRecord {
     79  public:
     80   Address from;
     81   Address to;
     82 
     83   INLINE(void UpdateCodeMap(CodeMap* code_map));
     84 };
     85 
     86 
     87 class ReportBuiltinEventRecord : public CodeEventRecord {
     88  public:
     89   Address start;
     90   Builtins::Name builtin_id;
     91 
     92   INLINE(void UpdateCodeMap(CodeMap* code_map));
     93 };
     94 
     95 
     96 class TickSampleEventRecord {
     97  public:
     98   // The parameterless constructor is used when we dequeue data from
     99   // the ticks buffer.
    100   TickSampleEventRecord() { }
    101   explicit TickSampleEventRecord(unsigned order) : order(order) { }
    102 
    103   unsigned order;
    104   TickSample sample;
    105 };
    106 
    107 
    108 class CodeEventsContainer {
    109  public:
    110   explicit CodeEventsContainer(
    111       CodeEventRecord::Type type = CodeEventRecord::NONE) {
    112     generic.type = type;
    113   }
    114   union  {
    115     CodeEventRecord generic;
    116 #define DECLARE_CLASS(ignore, type) type type##_;
    117     CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
    118 #undef DECLARE_TYPE
    119   };
    120 };
    121 
    122 
    123 // This class implements both the profile events processor thread and
    124 // methods called by event producers: VM and stack sampler threads.
    125 class ProfilerEventsProcessor : public base::Thread {
    126  public:
    127   ProfilerEventsProcessor(ProfileGenerator* generator,
    128                           Sampler* sampler,
    129                           base::TimeDelta period);
    130   virtual ~ProfilerEventsProcessor() {}
    131 
    132   // Thread control.
    133   virtual void Run();
    134   void StopSynchronously();
    135   INLINE(bool running()) { return running_; }
    136   void Enqueue(const CodeEventsContainer& event);
    137 
    138   // Puts current stack into tick sample events buffer.
    139   void AddCurrentStack(Isolate* isolate);
    140 
    141   // Tick sample events are filled directly in the buffer of the circular
    142   // queue (because the structure is of fixed width, but usually not all
    143   // stack frame entries are filled.) This method returns a pointer to the
    144   // next record of the buffer.
    145   inline TickSample* StartTickSample();
    146   inline void FinishTickSample();
    147 
    148   // SamplingCircularQueue has stricter alignment requirements than a normal new
    149   // can fulfil, so we need to provide our own new/delete here.
    150   void* operator new(size_t size);
    151   void operator delete(void* ptr);
    152 
    153  private:
    154   // Called from events processing thread (Run() method.)
    155   bool ProcessCodeEvent();
    156 
    157   enum SampleProcessingResult {
    158     OneSampleProcessed,
    159     FoundSampleForNextCodeEvent,
    160     NoSamplesInQueue
    161   };
    162   SampleProcessingResult ProcessOneSample();
    163 
    164   ProfileGenerator* generator_;
    165   Sampler* sampler_;
    166   bool running_;
    167   // Sampling period in microseconds.
    168   const base::TimeDelta period_;
    169   UnboundQueue<CodeEventsContainer> events_buffer_;
    170   static const size_t kTickSampleBufferSize = 1 * MB;
    171   static const size_t kTickSampleQueueLength =
    172       kTickSampleBufferSize / sizeof(TickSampleEventRecord);
    173   SamplingCircularQueue<TickSampleEventRecord,
    174                         kTickSampleQueueLength> ticks_buffer_;
    175   UnboundQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
    176   unsigned last_code_event_id_;
    177   unsigned last_processed_code_event_id_;
    178 };
    179 
    180 
    181 #define PROFILE(IsolateGetter, Call)                                        \
    182   do {                                                                      \
    183     Isolate* cpu_profiler_isolate = (IsolateGetter);                        \
    184     v8::internal::Logger* logger = cpu_profiler_isolate->logger();          \
    185     CpuProfiler* cpu_profiler = cpu_profiler_isolate->cpu_profiler();       \
    186     if (logger->is_logging_code_events() || cpu_profiler->is_profiling()) { \
    187       logger->Call;                                                         \
    188     }                                                                       \
    189   } while (false)
    190 
    191 
    192 class CpuProfiler : public CodeEventListener {
    193  public:
    194   explicit CpuProfiler(Isolate* isolate);
    195 
    196   CpuProfiler(Isolate* isolate,
    197               CpuProfilesCollection* test_collection,
    198               ProfileGenerator* test_generator,
    199               ProfilerEventsProcessor* test_processor);
    200 
    201   virtual ~CpuProfiler();
    202 
    203   void set_sampling_interval(base::TimeDelta value);
    204   void StartProfiling(const char* title, bool record_samples = false);
    205   void StartProfiling(String* title, bool record_samples);
    206   CpuProfile* StopProfiling(const char* title);
    207   CpuProfile* StopProfiling(String* title);
    208   int GetProfilesCount();
    209   CpuProfile* GetProfile(int index);
    210   void DeleteAllProfiles();
    211   void DeleteProfile(CpuProfile* profile);
    212 
    213   // Invoked from stack sampler (thread or signal handler.)
    214   inline TickSample* StartTickSample();
    215   inline void FinishTickSample();
    216 
    217   // Must be called via PROFILE macro, otherwise will crash when
    218   // profiling is not enabled.
    219   virtual void CallbackEvent(Name* name, Address entry_point);
    220   virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
    221                                Code* code, const char* comment);
    222   virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
    223                                Code* code, Name* name);
    224   virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
    225                                SharedFunctionInfo* shared,
    226                                CompilationInfo* info, Name* script_name);
    227   virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code,
    228                                SharedFunctionInfo* shared,
    229                                CompilationInfo* info, Name* script_name,
    230                                int line, int column);
    231   virtual void CodeCreateEvent(Logger::LogEventsAndTags tag,
    232                                Code* code, int args_count);
    233   virtual void CodeMovingGCEvent() {}
    234   virtual void CodeMoveEvent(Address from, Address to);
    235   virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared);
    236   virtual void CodeDeleteEvent(Address from);
    237   virtual void GetterCallbackEvent(Name* name, Address entry_point);
    238   virtual void RegExpCodeCreateEvent(Code* code, String* source);
    239   virtual void SetterCallbackEvent(Name* name, Address entry_point);
    240   virtual void SharedFunctionInfoMoveEvent(Address from, Address to);
    241 
    242   INLINE(bool is_profiling() const) { return is_profiling_; }
    243   bool* is_profiling_address() {
    244     return &is_profiling_;
    245   }
    246 
    247   ProfileGenerator* generator() const { return generator_; }
    248   ProfilerEventsProcessor* processor() const { return processor_; }
    249   Isolate* isolate() const { return isolate_; }
    250 
    251  private:
    252   void StartProcessorIfNotStarted();
    253   void StopProcessorIfLastProfile(const char* title);
    254   void StopProcessor();
    255   void ResetProfiles();
    256   void LogBuiltins();
    257 
    258   Isolate* isolate_;
    259   base::TimeDelta sampling_interval_;
    260   CpuProfilesCollection* profiles_;
    261   ProfileGenerator* generator_;
    262   ProfilerEventsProcessor* processor_;
    263   bool saved_is_logging_;
    264   bool is_profiling_;
    265 
    266   DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
    267 };
    268 
    269 } }  // namespace v8::internal
    270 
    271 
    272 #endif  // V8_CPU_PROFILER_H_
    273