LCOV - code coverage report
Current view: top level - src/profiler - cpu-profiler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 3 3 100.0 %
Date: 2019-04-19 Functions: 1 2 50.0 %

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

Generated by: LCOV version 1.10