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-03-21 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       67035 :   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     5451233 :     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        1600 : class ProfilerEventsProcessor : public base::Thread, public CodeEventObserver {
     136             :  public:
     137             :   virtual ~ProfilerEventsProcessor();
     138             : 
     139             :   void CodeEventHandler(const CodeEventsContainer& evt_rec) override;
     140             : 
     141             :   // Thread control.
     142             :   void Run() override = 0;
     143             :   void StopSynchronously();
     144             :   V8_INLINE bool running() { return !!base::Relaxed_Load(&running_); }
     145             :   void Enqueue(const CodeEventsContainer& event);
     146             : 
     147             :   // Puts current stack into the tick sample events buffer.
     148             :   void AddCurrentStack(bool update_stats = false);
     149             :   void AddDeoptStack(Address from, int fp_to_sp_delta);
     150             :   // Add a sample into the tick sample events buffer. Used for testing.
     151             :   void AddSample(TickSample sample);
     152             : 
     153             :  protected:
     154             :   ProfilerEventsProcessor(Isolate* isolate, ProfileGenerator* generator);
     155             : 
     156             :   // Called from events processing thread (Run() method.)
     157             :   bool ProcessCodeEvent();
     158             : 
     159             :   enum SampleProcessingResult {
     160             :     OneSampleProcessed,
     161             :     FoundSampleForNextCodeEvent,
     162             :     NoSamplesInQueue
     163             :   };
     164             :   virtual SampleProcessingResult ProcessOneSample() = 0;
     165             : 
     166             :   ProfileGenerator* generator_;
     167             :   base::Atomic32 running_;
     168             :   base::ConditionVariable running_cond_;
     169             :   base::Mutex running_mutex_;
     170             :   LockedQueue<CodeEventsContainer> events_buffer_;
     171             :   LockedQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
     172             :   std::atomic<unsigned> last_code_event_id_;
     173             :   unsigned last_processed_code_event_id_;
     174             :   Isolate* isolate_;
     175             : };
     176             : 
     177             : class SamplingEventsProcessor : public ProfilerEventsProcessor {
     178             :  public:
     179             :   SamplingEventsProcessor(Isolate* isolate, ProfileGenerator* generator,
     180             :                           base::TimeDelta period);
     181             :   ~SamplingEventsProcessor() override;
     182             : 
     183             :   // SamplingCircularQueue has stricter alignment requirements than a normal new
     184             :   // can fulfil, so we need to provide our own new/delete here.
     185             :   void* operator new(size_t size);
     186             :   void operator delete(void* ptr);
     187             : 
     188             :   void Run() override;
     189             : 
     190             :   // Tick sample events are filled directly in the buffer of the circular
     191             :   // queue (because the structure is of fixed width, but usually not all
     192             :   // stack frame entries are filled.) This method returns a pointer to the
     193             :   // next record of the buffer.
     194             :   // These methods are not thread-safe and should only ever be called by one
     195             :   // producer (from CpuSampler::SampleStack()). For testing, use AddSample.
     196             :   inline TickSample* StartTickSample();
     197             :   inline void FinishTickSample();
     198             : 
     199             :   sampler::Sampler* sampler() { return sampler_.get(); }
     200             : 
     201             :  private:
     202             :   SampleProcessingResult ProcessOneSample() override;
     203             : 
     204             :   static const size_t kTickSampleBufferSize = 512 * KB;
     205             :   static const size_t kTickSampleQueueLength =
     206             :       kTickSampleBufferSize / sizeof(TickSampleEventRecord);
     207             :   SamplingCircularQueue<TickSampleEventRecord,
     208             :                         kTickSampleQueueLength> ticks_buffer_;
     209             :   std::unique_ptr<sampler::Sampler> sampler_;
     210             :   const base::TimeDelta period_;  // Samples & code events processing period.
     211             : };
     212             : 
     213             : class CpuProfiler {
     214             :  public:
     215             :   explicit CpuProfiler(Isolate* isolate);
     216             : 
     217             :   CpuProfiler(Isolate* isolate, CpuProfilesCollection* profiles,
     218             :               ProfileGenerator* test_generator,
     219             :               ProfilerEventsProcessor* test_processor);
     220             : 
     221             :   ~CpuProfiler();
     222             : 
     223             :   static void CollectSample(Isolate* isolate);
     224             : 
     225             :   typedef v8::CpuProfilingMode ProfilingMode;
     226             : 
     227             :   void set_sampling_interval(base::TimeDelta value);
     228             :   void CollectSample();
     229             :   void StartProfiling(const char* title, bool record_samples = false,
     230             :                       ProfilingMode mode = ProfilingMode::kLeafNodeLineNumbers);
     231             :   void StartProfiling(String title, bool record_samples, ProfilingMode mode);
     232             :   CpuProfile* StopProfiling(const char* title);
     233             :   CpuProfile* StopProfiling(String title);
     234             :   int GetProfilesCount();
     235             :   CpuProfile* GetProfile(int index);
     236             :   void DeleteAllProfiles();
     237             :   void DeleteProfile(CpuProfile* profile);
     238             : 
     239             :   bool is_profiling() const { return is_profiling_; }
     240             : 
     241             :   ProfileGenerator* generator() const { return generator_.get(); }
     242             :   ProfilerEventsProcessor* processor() const { return processor_.get(); }
     243             :   Isolate* isolate() const { return isolate_; }
     244             : 
     245             :   ProfilerListener* profiler_listener_for_test() {
     246             :     return profiler_listener_.get();
     247             :   }
     248             : 
     249             :  private:
     250             :   void StartProcessorIfNotStarted();
     251             :   void StopProcessorIfLastProfile(const char* title);
     252             :   void StopProcessor();
     253             :   void ResetProfiles();
     254             :   void LogBuiltins();
     255             :   void CreateEntriesForRuntimeCallStats();
     256             : 
     257             :   Isolate* const isolate_;
     258             :   base::TimeDelta sampling_interval_;
     259             :   std::unique_ptr<CpuProfilesCollection> profiles_;
     260             :   std::unique_ptr<ProfileGenerator> generator_;
     261             :   std::unique_ptr<ProfilerEventsProcessor> processor_;
     262             :   std::unique_ptr<ProfilerListener> profiler_listener_;
     263             :   bool saved_is_logging_;
     264             :   bool is_profiling_;
     265             : 
     266             :   DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
     267             : };
     268             : 
     269             : }  // namespace internal
     270             : }  // namespace v8
     271             : 
     272             : #endif  // V8_PROFILER_CPU_PROFILER_H_

Generated by: LCOV version 1.10