Home | History | Annotate | Download | only in profiler
      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_PROFILER_CPU_PROFILER_H_
      6 #define V8_PROFILER_CPU_PROFILER_H_
      7 
      8 #include <memory>
      9 
     10 #include "src/allocation.h"
     11 #include "src/base/atomic-utils.h"
     12 #include "src/base/atomicops.h"
     13 #include "src/base/platform/time.h"
     14 #include "src/isolate.h"
     15 #include "src/libsampler/sampler.h"
     16 #include "src/locked-queue.h"
     17 #include "src/profiler/circular-queue.h"
     18 #include "src/profiler/profiler-listener.h"
     19 #include "src/profiler/tick-sample.h"
     20 
     21 namespace v8 {
     22 namespace internal {
     23 
     24 // Forward declarations.
     25 class CodeEntry;
     26 class CodeMap;
     27 class CpuProfile;
     28 class CpuProfilesCollection;
     29 class ProfileGenerator;
     30 
     31 #define CODE_EVENTS_TYPE_LIST(V)                         \
     32   V(CODE_CREATION, CodeCreateEventRecord)                \
     33   V(CODE_MOVE, CodeMoveEventRecord)                      \
     34   V(CODE_DISABLE_OPT, CodeDisableOptEventRecord)         \
     35   V(CODE_DEOPT, CodeDeoptEventRecord)                    \
     36   V(REPORT_BUILTIN, ReportBuiltinEventRecord)
     37 
     38 
     39 class CodeEventRecord {
     40  public:
     41 #define DECLARE_TYPE(type, ignore) type,
     42   enum Type {
     43     NONE = 0,
     44     CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
     45     NUMBER_OF_TYPES
     46   };
     47 #undef DECLARE_TYPE
     48 
     49   Type type;
     50   mutable unsigned order;
     51 };
     52 
     53 
     54 class CodeCreateEventRecord : public CodeEventRecord {
     55  public:
     56   Address instruction_start;
     57   CodeEntry* entry;
     58   unsigned instruction_size;
     59 
     60   V8_INLINE void UpdateCodeMap(CodeMap* code_map);
     61 };
     62 
     63 
     64 class CodeMoveEventRecord : public CodeEventRecord {
     65  public:
     66   Address from_instruction_start;
     67   Address to_instruction_start;
     68 
     69   V8_INLINE void UpdateCodeMap(CodeMap* code_map);
     70 };
     71 
     72 
     73 class CodeDisableOptEventRecord : public CodeEventRecord {
     74  public:
     75   Address instruction_start;
     76   const char* bailout_reason;
     77 
     78   V8_INLINE void UpdateCodeMap(CodeMap* code_map);
     79 };
     80 
     81 
     82 class CodeDeoptEventRecord : public CodeEventRecord {
     83  public:
     84   Address instruction_start;
     85   const char* deopt_reason;
     86   int deopt_id;
     87   Address pc;
     88   int fp_to_sp_delta;
     89   CpuProfileDeoptFrame* deopt_frames;
     90   int deopt_frame_count;
     91 
     92   V8_INLINE void UpdateCodeMap(CodeMap* code_map);
     93 };
     94 
     95 
     96 class ReportBuiltinEventRecord : public CodeEventRecord {
     97  public:
     98   Address instruction_start;
     99   Builtins::Name builtin_id;
    100 
    101   V8_INLINE void UpdateCodeMap(CodeMap* code_map);
    102 };
    103 
    104 
    105 class TickSampleEventRecord {
    106  public:
    107   // The parameterless constructor is used when we dequeue data from
    108   // the ticks buffer.
    109   TickSampleEventRecord() { }
    110   explicit TickSampleEventRecord(unsigned order) : order(order) { }
    111 
    112   unsigned order;
    113   TickSample sample;
    114 };
    115 
    116 
    117 class CodeEventsContainer {
    118  public:
    119   explicit CodeEventsContainer(
    120       CodeEventRecord::Type type = CodeEventRecord::NONE) {
    121     generic.type = type;
    122   }
    123   union  {
    124     CodeEventRecord generic;
    125 #define DECLARE_CLASS(ignore, type) type type##_;
    126     CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
    127 #undef DECLARE_CLASS
    128   };
    129 };
    130 
    131 
    132 // This class implements both the profile events processor thread and
    133 // methods called by event producers: VM and stack sampler threads.
    134 class ProfilerEventsProcessor : public base::Thread {
    135  public:
    136   ProfilerEventsProcessor(Isolate* isolate, ProfileGenerator* generator,
    137                           base::TimeDelta period);
    138   virtual ~ProfilerEventsProcessor();
    139 
    140   // Thread control.
    141   virtual void Run();
    142   void StopSynchronously();
    143   V8_INLINE bool running() { return !!base::Relaxed_Load(&running_); }
    144   void Enqueue(const CodeEventsContainer& event);
    145 
    146   // Puts current stack into tick sample events buffer.
    147   void AddCurrentStack(Isolate* isolate, bool update_stats = false);
    148   void AddDeoptStack(Isolate* isolate, Address from, int fp_to_sp_delta);
    149 
    150   // Tick sample events are filled directly in the buffer of the circular
    151   // queue (because the structure is of fixed width, but usually not all
    152   // stack frame entries are filled.) This method returns a pointer to the
    153   // next record of the buffer.
    154   inline TickSample* StartTickSample();
    155   inline void FinishTickSample();
    156 
    157   // SamplingCircularQueue has stricter alignment requirements than a normal new
    158   // can fulfil, so we need to provide our own new/delete here.
    159   void* operator new(size_t size);
    160   void operator delete(void* ptr);
    161 
    162   sampler::Sampler* sampler() { return sampler_.get(); }
    163 
    164  private:
    165   // Called from events processing thread (Run() method.)
    166   bool ProcessCodeEvent();
    167 
    168   enum SampleProcessingResult {
    169     OneSampleProcessed,
    170     FoundSampleForNextCodeEvent,
    171     NoSamplesInQueue
    172   };
    173   SampleProcessingResult ProcessOneSample();
    174 
    175   ProfileGenerator* generator_;
    176   std::unique_ptr<sampler::Sampler> sampler_;
    177   base::Atomic32 running_;
    178   const base::TimeDelta period_;  // Samples & code events processing period.
    179   LockedQueue<CodeEventsContainer> events_buffer_;
    180   static const size_t kTickSampleBufferSize = 1 * MB;
    181   static const size_t kTickSampleQueueLength =
    182       kTickSampleBufferSize / sizeof(TickSampleEventRecord);
    183   SamplingCircularQueue<TickSampleEventRecord,
    184                         kTickSampleQueueLength> ticks_buffer_;
    185   LockedQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
    186   std::atomic<unsigned> last_code_event_id_;
    187   unsigned last_processed_code_event_id_;
    188 };
    189 
    190 class CpuProfiler : public CodeEventObserver {
    191  public:
    192   explicit CpuProfiler(Isolate* isolate);
    193 
    194   CpuProfiler(Isolate* isolate, CpuProfilesCollection* profiles,
    195               ProfileGenerator* test_generator,
    196               ProfilerEventsProcessor* test_processor);
    197 
    198   ~CpuProfiler() override;
    199 
    200   static void CollectSample(Isolate* isolate);
    201 
    202   typedef v8::CpuProfilingMode ProfilingMode;
    203 
    204   void set_sampling_interval(base::TimeDelta value);
    205   void CollectSample();
    206   void StartProfiling(const char* title, bool record_samples = false,
    207                       ProfilingMode mode = ProfilingMode::kLeafNodeLineNumbers);
    208   void StartProfiling(String* title, bool record_samples, ProfilingMode mode);
    209   CpuProfile* StopProfiling(const char* title);
    210   CpuProfile* StopProfiling(String* title);
    211   int GetProfilesCount();
    212   CpuProfile* GetProfile(int index);
    213   void DeleteAllProfiles();
    214   void DeleteProfile(CpuProfile* profile);
    215 
    216   void CodeEventHandler(const CodeEventsContainer& evt_rec) override;
    217 
    218   bool is_profiling() const { return is_profiling_; }
    219 
    220   ProfileGenerator* generator() const { return generator_.get(); }
    221   ProfilerEventsProcessor* processor() const { return processor_.get(); }
    222   Isolate* isolate() const { return isolate_; }
    223 
    224   ProfilerListener* profiler_listener_for_test() {
    225     return profiler_listener_.get();
    226   }
    227 
    228  private:
    229   void StartProcessorIfNotStarted();
    230   void StopProcessorIfLastProfile(const char* title);
    231   void StopProcessor();
    232   void ResetProfiles();
    233   void LogBuiltins();
    234   void CreateEntriesForRuntimeCallStats();
    235 
    236   Isolate* const isolate_;
    237   base::TimeDelta sampling_interval_;
    238   std::unique_ptr<CpuProfilesCollection> profiles_;
    239   std::unique_ptr<ProfileGenerator> generator_;
    240   std::unique_ptr<ProfilerEventsProcessor> processor_;
    241   std::unique_ptr<ProfilerListener> profiler_listener_;
    242   bool saved_is_logging_;
    243   bool is_profiling_;
    244 
    245   DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
    246 };
    247 
    248 }  // namespace internal
    249 }  // namespace v8
    250 
    251 #endif  // V8_PROFILER_CPU_PROFILER_H_
    252