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 */
013package org.mmtk.utility.statistics;
014
015import org.mmtk.utility.Log;
016
017import org.mmtk.vm.VM;
018
019import 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
026public 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}