1 /* 2 * Copyright (c) 2012, 2013, 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_IMPLEMENTATION_SHARED_GCTIMER_HPP 26 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTIMER_HPP 27 28 #include "memory/allocation.hpp" 29 #include "prims/jni_md.h" 30 #include "utilities/macros.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 virtual void visit(PausePhase* phase) { visit((GCPhase*)phase); } 42 virtual void visit(ConcurrentPhase* phase) { visit((GCPhase*)phase); } 43 }; 44 45 class GCPhase { 46 const char* _name; 47 int _level; 48 jlong _start; 49 jlong _end; 50 51 public: 52 void set_name(const char* name) { _name = name; } 53 const char* name() { return _name; } 54 55 int level() { return _level; } 56 void set_level(int level) { _level = level; } 57 58 jlong start() { return _start; } 59 void set_start(jlong time) { _start = time; } 60 61 jlong end() { return _end; } 62 void set_end(jlong time) { _end = time; } 63 64 virtual void accept(PhaseVisitor* visitor) = 0; 65 }; 66 67 class PausePhase : public GCPhase { 68 public: 69 void accept(PhaseVisitor* visitor) { 70 visitor->visit(this); 71 } 72 }; 73 74 class ConcurrentPhase : public GCPhase { 75 void accept(PhaseVisitor* visitor) { 76 visitor->visit(this); 77 } 78 }; 79 80 class PhasesStack { 81 public: 82 // FIXME: Temporary set to 5 (used to be 4), since Reference processing needs it. 83 static const int PHASE_LEVELS = 5; 84 85 private: 86 int _phase_indices[PHASE_LEVELS]; 87 int _next_phase_level; 88 89 public: 90 PhasesStack() { clear(); } 91 void clear(); 92 93 void push(int phase_index); 94 int pop(); 95 int count() const; 96 }; 97 98 class TimePartitions { 99 static const int INITIAL_CAPACITY = 10; 100 101 // Currently we only support pause phases. 102 GrowableArray<PausePhase>* _phases; 103 PhasesStack _active_phases; 104 105 jlong _sum_of_pauses; 106 jlong _longest_pause; 107 108 public: 109 TimePartitions(); 110 ~TimePartitions(); 111 void clear(); 112 113 void report_gc_phase_start(const char* name, jlong time); 114 void report_gc_phase_end(jlong time); 115 116 int num_phases() const; 117 GCPhase* phase_at(int index) const; 118 119 jlong sum_of_pauses(); 120 jlong longest_pause(); 121 122 bool has_active_phases(); 123 private: 124 void update_statistics(GCPhase* phase); 125 }; 126 127 class PhasesIterator { 128 public: 129 virtual bool has_next() = 0; 130 virtual GCPhase* next() = 0; 131 }; 132 133 class GCTimer : public ResourceObj { 134 NOT_PRODUCT(friend class GCTimerTest;) 135 protected: 136 jlong _gc_start; 137 jlong _gc_end; 138 TimePartitions _time_partitions; 139 140 public: 141 virtual void register_gc_start(jlong time); 142 virtual void register_gc_end(jlong time); 143 144 void register_gc_phase_start(const char* name, jlong time); 145 void register_gc_phase_end(jlong time); 146 147 jlong gc_start() { return _gc_start; } 148 jlong gc_end() { return _gc_end; } 149 150 TimePartitions* time_partitions() { return &_time_partitions; } 151 152 long longest_pause(); 153 long sum_of_pauses(); 154 155 protected: 156 void register_gc_pause_start(const char* name, jlong time); 157 void register_gc_pause_end(jlong time); 158 }; 159 160 class STWGCTimer : public GCTimer { 161 public: 162 virtual void register_gc_start(jlong time); 163 virtual void register_gc_end(jlong time); 164 }; 165 166 class ConcurrentGCTimer : public GCTimer { 167 public: 168 void register_gc_pause_start(const char* name, jlong time); 169 void register_gc_pause_end(jlong time); 170 }; 171 172 class TimePartitionPhasesIterator { 173 TimePartitions* _time_partitions; 174 int _next; 175 176 public: 177 TimePartitionPhasesIterator(TimePartitions* time_partitions) : _time_partitions(time_partitions), _next(0) { } 178 179 virtual bool has_next(); 180 virtual GCPhase* next(); 181 }; 182 183 184 /////////////// Unit tests /////////////// 185 186 #ifndef PRODUCT 187 188 class GCTimerAllTest { 189 public: 190 static void all(); 191 }; 192 193 #endif 194 195 #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTIMER_HPP