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
026    public class BooleanCounter extends Counter {
027    
028      /****************************************************************************
029       *
030       * Instance variables
031       */
032    
033      /**
034       *
035       */
036      private final boolean[] state;
037    
038      protected int total = 0;
039      private boolean running = false;
040    
041      /****************************************************************************
042       *
043       * Initialization
044       */
045    
046      /**
047       * Constructor
048       *
049       * @param name The name to be associated with this counter
050       */
051      public BooleanCounter(String name) {
052        this(name, true, false);
053      }
054    
055      /**
056       * Constructor
057       *
058       * @param name The name to be associated with this counter
059       * @param start {@code true} if this counter is to be implicitly started
060       * when <code>startAll()</code> is called (otherwise the counter
061       * must be explicitly started).
062       */
063      public BooleanCounter(String name, boolean start) {
064        this(name, start, false);
065      }
066    
067      /**
068       * Constructor
069       *
070       * @param name The name to be associated with this counter
071       * @param start True if this counter is to be implicitly started
072       * when <code>startAll()</code> is called (otherwise the counter
073       * must be explicitly started).
074       * @param mergephases True if this counter does not separately
075       * report GC and Mutator phases.
076       */
077      public BooleanCounter(String name, boolean start, boolean mergephases) {
078        super(name, start, mergephases);
079        state = new boolean[Stats.MAX_PHASES];
080      }
081    
082      /****************************************************************************
083       *
084       * Counter-specific methods
085       */
086    
087      /**
088       * Set the boolean to {@code true} for this phase, increment the total.
089       */
090      public void set() {
091        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Stats.phase == Stats.MAX_PHASES -1 || !state[Stats.phase]);
092        state[Stats.phase] = true;
093        total++;
094      }
095    
096      /****************************************************************************
097       *
098       * Generic counter control methods: start, stop, print etc
099       */
100    
101      /**
102       * {@inheritDoc}
103       */
104      @Override
105      protected void start() {
106        if (!Stats.gatheringStats) return;
107        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!running);
108        running = true;
109      }
110    
111      @Override
112      protected void stop() {
113        if (!Stats.gatheringStats) return;
114        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(running);
115        running = false;
116      }
117    
118      /**
119       * The phase has changed (from GC to mutator or mutator to GC).
120       * Take action with respect to the last phase if necessary.
121       * <b>Do nothing in this case.</b>
122       *
123       * @param oldPhase The last phase
124       */
125      @Override
126      void phaseChange(int oldPhase) {}
127    
128      /**
129       * {@inheritDoc}
130       * Print '0' for {@code false}, '1' for {@code true}.
131       *
132       * @param phase The phase to be printed
133       */
134      @Override
135      protected final void printCount(int phase) {
136        if (VM.VERIFY_ASSERTIONS && mergePhases())
137          if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((phase | 1) == (phase + 1));
138        if (mergePhases())
139          printValue((state[phase] || state[phase + 1]) ? 1 : 0);
140        else
141          printValue((state[phase]) ? 1 : 0);
142      }
143    
144      /**
145       * Print the current total number of {@code true} phases for this counter
146       */
147      @Override
148      protected final void printTotal() {
149        int total = 0;
150        for (int p = 0; p <= Stats.phase; p++) {
151          total += (state[p]) ? 1 : 0;
152        }
153        printValue(total);
154      }
155    
156      @Override
157      protected final void printTotal(boolean mutator) {
158        int total = 0;
159        for (int p = (mutator) ? 0 : 1; p <= Stats.phase; p += 2) {
160          total += (state[p]) ? 1 : 0;
161        }
162        printValue(total);
163      }
164    
165      /**
166       * {@inheritDoc}
167       * <b>Do nothing in this case.</b>
168       */
169      @Override
170      protected final void printMin(boolean mutator) {}
171    
172      /**
173       * {@inheritDoc}
174       * <b>Do nothing in this case.</b>
175       */
176      @Override
177      protected final void printMax(boolean mutator) {}
178    
179      /**
180       * Print the given value
181       *
182       * @param value The value to be printed
183       */
184      void printValue(int value) {
185        Log.write(value);
186      }
187    
188      @Override
189      public void printLast() {
190        if (Stats.phase > 0) printCount(Stats.phase - 1);
191      }
192    }