001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Eclipse Public License (EPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.mmtk.utility.statistics;
014
015 import org.mmtk.utility.Log;
016
017 import org.mmtk.vm.VM;
018
019 import org.vmmagic.pragma.*;
020
021 /**
022 * This class implements a simple boolean counter (counting number of
023 * phases where some boolean event is true).
024 */
025 @Uninterruptible public class BooleanCounter extends Counter {
026
027 /****************************************************************************
028 *
029 * Instance variables
030 */
031
032 private final boolean[] state;
033
034 protected int total = 0;
035 private boolean running = false;
036
037 /****************************************************************************
038 *
039 * Initialization
040 */
041
042 /**
043 * Constructor
044 *
045 * @param name The name to be associated with this counter
046 */
047 public BooleanCounter(String name) {
048 this(name, true, false);
049 }
050
051 /**
052 * Constructor
053 *
054 * @param name The name to be associated with this counter
055 * @param start True if this counter is to be implicitly started
056 * when <code>startAll()</code> is called (otherwise the counter
057 * must be explicitly started).
058 */
059 public BooleanCounter(String name, boolean start) {
060 this(name, start, false);
061 }
062
063 /**
064 * Constructor
065 *
066 * @param name The name to be associated with this counter
067 * @param start True if this counter is to be implicitly started
068 * when <code>startAll()</code> is called (otherwise the counter
069 * must be explicitly started).
070 * @param mergephases True if this counter does not separately
071 * report GC and Mutator phases.
072 */
073 public BooleanCounter(String name, boolean start, boolean mergephases) {
074 super(name, start, mergephases);
075 state = new boolean[Stats.MAX_PHASES];
076 for (int i = 0; i < Stats.MAX_PHASES; i++)
077 state[i] = false;
078 }
079
080 /****************************************************************************
081 *
082 * Counter-specific methods
083 */
084
085 /**
086 * Set the boolean to true for this phase, increment the total.
087 */
088 public void set() {
089 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Stats.phase == Stats.MAX_PHASES -1 || !state[Stats.phase]);
090 state[Stats.phase] = true;
091 total++;
092 }
093
094 /****************************************************************************
095 *
096 * Generic counter control methods: start, stop, print etc
097 */
098
099 /**
100 * Start this counter
101 */
102 protected void start() {
103 if (!Stats.gatheringStats) return;
104 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!running);
105 running = true;
106 }
107
108 /**
109 * Stop this counter
110 */
111 protected void stop() {
112 if (!Stats.gatheringStats) return;
113 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(running);
114 running = false;
115 }
116
117 /**
118 * The phase has changed (from GC to mutator or mutator to GC).
119 * Take action with respect to the last phase if necessary.
120 * <b>Do nothing in this case.</b>
121 *
122 * @param oldPhase The last phase
123 */
124 void phaseChange(int oldPhase) {}
125
126 /**
127 * Print the value of this counter for the given phase. Print '0'
128 * for false, '1' for true.
129 *
130 * @param phase The phase to be printed
131 */
132 protected final void printCount(int phase) {
133 if (VM.VERIFY_ASSERTIONS && mergePhases())
134 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((phase | 1) == (phase + 1));
135 if (mergePhases())
136 printValue((state[phase] || state[phase + 1]) ? 1 : 0);
137 else
138 printValue((state[phase]) ? 1 : 0);
139 }
140
141 /**
142 * Print the current total number of 'true' phases for this counter
143 */
144 protected final void printTotal() {
145 int total = 0;
146 for (int p = 0; p <= Stats.phase; p++) {
147 total += (state[p]) ? 1 : 0;
148 }
149 printValue(total);
150 }
151
152 /**
153 * Print the current total number of 'true' phases for either the
154 * mutator or GC phase
155 *
156 * @param mutator True if the total for the mutator phases is to be
157 * printed (otherwise the total for the GC phases will be printed).
158 */
159 protected final void printTotal(boolean mutator) {
160 int total = 0;
161 for (int p = (mutator) ? 0 : 1; p <= Stats.phase; p += 2) {
162 total += (state[p]) ? 1 : 0;
163 }
164 printValue(total);
165 }
166
167 /**
168 * Print the current minimum value for either the mutator or GC
169 * phase. <b>Do nothing in this case.</b>
170 *
171 * @param mutator True if the minimum for the mutator phase is to be
172 * printed (otherwise the minimum for the GC phase will be printed).
173 */
174 protected final void printMin(boolean mutator) {}
175
176 /**
177 * Print the current maximum value for either the mutator or GC
178 * phase. <b>Do nothing in this case.</b>
179 *
180 * @param mutator True if the maximum for the mutator phase is to be
181 * printed (otherwise the maximum for the GC phase will be printed).
182 */
183 protected final void printMax(boolean mutator) {}
184
185 /**
186 * Print the given value
187 *
188 * @param value The value to be printed
189 */
190 void printValue(int value) {
191 Log.write(value);
192 }
193
194 /**
195 * Print statistics for the most recent phase
196 */
197 public void printLast() {
198 if (Stats.phase > 0) printCount(Stats.phase - 1);
199 }
200 }