1 /*
   2  * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_GC_SHARED_GCTIMER_HPP
  26 #define SHARE_VM_GC_SHARED_GCTIMER_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "utilities/macros.hpp"
  30 #include "utilities/ticks.hpp"
  31 
  32 class ConcurrentPhase;
  33 class GCPhase;
  34 class PausePhase;
  35 
  36 template <class E> class GrowableArray;
  37 
  38 class PhaseVisitor {
  39  public:
  40   virtual void visit(GCPhase* phase) = 0;
  41 };
  42 
  43 class GCPhase {
  44  public:
  45   enum PhaseType {
  46     PausePhaseType      = 0,
  47     ConcurrentPhaseType = 1
  48   };
  49 
  50  private:
  51   const char* _name;
  52   int _level;
  53   Ticks _start;
  54   Ticks _end;
  55   PhaseType _type;
  56 
  57  public:
  58   void set_name(const char* name) { _name = name; }
  59   const char* name() const { return _name; }
  60 
  61   int level() const { return _level; }
  62   void set_level(int level) { _level = level; }
  63 
  64   const Ticks start() const { return _start; }
  65   void set_start(const Ticks& time) { _start = time; }
  66 
  67   const Ticks end() const { return _end; }
  68   void set_end(const Ticks& time) { _end = time; }
  69 
  70   PhaseType type() const { return _type; }
  71   void set_type(PhaseType type) { _type = type; }
  72 
  73   void accept(PhaseVisitor* visitor) {
  74     visitor->visit(this);
  75   }
  76 };
  77 
  78 class PhasesStack {
  79  public:
  80   // Set to 6, since Reference processing needs it.
  81   static const int PHASE_LEVELS = 6;
  82 
  83  private:
  84   int _phase_indices[PHASE_LEVELS];
  85   int _next_phase_level;
  86 
  87  public:
  88   PhasesStack() { clear(); }
  89   void clear();
  90 
  91   void push(int phase_index);
  92   int pop();
  93   int count() const;
  94 };
  95 
  96 class TimePartitions {
  97   static const int INITIAL_CAPACITY = 10;
  98 
  99   GrowableArray<GCPhase>* _phases;
 100   PhasesStack _active_phases;
 101 
 102   Tickspan _sum_of_pauses;
 103   Tickspan _longest_pause;
 104 
 105  public:
 106   TimePartitions();
 107   ~TimePartitions();
 108   void clear();
 109 
 110   void report_gc_phase_start(const char* name, const Ticks& time, GCPhase::PhaseType type=GCPhase::PausePhaseType);
 111   void report_gc_phase_end(const Ticks& time, GCPhase::PhaseType type=GCPhase::PausePhaseType);
 112 
 113   int num_phases() const;
 114   GCPhase* phase_at(int index) const;
 115 
 116   const Tickspan sum_of_pauses() const { return _sum_of_pauses; }
 117   const Tickspan longest_pause() const { return _longest_pause; }
 118 
 119   bool has_active_phases();
 120 
 121  private:
 122   void update_statistics(GCPhase* phase);
 123 };
 124 
 125 class PhasesIterator {
 126  public:
 127   virtual bool has_next() = 0;
 128   virtual GCPhase* next() = 0;
 129 };
 130 
 131 class GCTimer : public ResourceObj {
 132  protected:
 133   Ticks _gc_start;
 134   Ticks _gc_end;
 135   TimePartitions _time_partitions;
 136 
 137  public:
 138   virtual void register_gc_start(const Ticks& time = Ticks::now());
 139   virtual void register_gc_end(const Ticks& time = Ticks::now());
 140 
 141   void register_gc_phase_start(const char* name, const Ticks& time);
 142   void register_gc_phase_end(const Ticks& time);
 143 
 144   const Ticks gc_start() const { return _gc_start; }
 145   const Ticks gc_end() const { return _gc_end; }
 146 
 147   TimePartitions* time_partitions() { return &_time_partitions; }
 148 
 149  protected:
 150   void register_gc_pause_start(const char* name, const Ticks& time = Ticks::now());
 151   void register_gc_pause_end(const Ticks& time = Ticks::now());
 152 };
 153 
 154 class STWGCTimer : public GCTimer {
 155  public:
 156   virtual void register_gc_start(const Ticks& time = Ticks::now());
 157   virtual void register_gc_end(const Ticks& time = Ticks::now());
 158 };
 159 
 160 class ConcurrentGCTimer : public GCTimer {
 161   // ConcurrentGCTimer can't be used if there is an overlap between a pause phase and a concurrent phase.
 162   // _is_concurrent_phase_active is used to find above case.
 163   bool _is_concurrent_phase_active;
 164 
 165  public:
 166   ConcurrentGCTimer(): GCTimer(), _is_concurrent_phase_active(false) {};
 167 
 168   void register_gc_pause_start(const char* name, const Ticks& time = Ticks::now());
 169   void register_gc_pause_end(const Ticks& time = Ticks::now());
 170 
 171   void register_gc_concurrent_start(const char* name, const Ticks& time = Ticks::now());
 172   void register_gc_concurrent_end(const Ticks& time = Ticks::now());
 173 };
 174 
 175 class TimePartitionPhasesIterator {
 176   TimePartitions* _time_partitions;
 177   int _next;
 178 
 179  public:
 180   TimePartitionPhasesIterator(TimePartitions* time_partitions) : _time_partitions(time_partitions), _next(0) { }
 181 
 182   virtual bool has_next();
 183   virtual GCPhase* next();
 184 };
 185 
 186 #endif // SHARE_VM_GC_SHARED_GCTIMER_HPP