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    }