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 event counter (counting number
023     * events that occur for each phase).
024     */
025    @Uninterruptible
026    public class EventCounter extends Counter {
027    
028      /****************************************************************************
029       *
030       * Instance variables
031       */
032    
033      /**
034       *
035       */
036      private final long[] count;
037    
038      protected long currentCount = 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 EventCounter(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 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 EventCounter(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 {@code 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 {@code true} if this counter does not separately
075       * report GC and Mutator phases.
076       */
077      public EventCounter(String name, boolean start, boolean mergephases) {
078        super(name, start, mergephases);
079        count = new long[Stats.MAX_PHASES];
080      }
081    
082      /****************************************************************************
083       *
084       * Counter-specific methods
085       */
086    
087      /**
088       * Increment the event counter
089       */
090      public void inc() {
091        if (running) inc(1);
092      }
093    
094      /**
095       * Increment the event counter by <code>value</code>
096       *
097       * @param value The amount by which the counter should be incremented.
098       */
099      public void inc(int value) {
100        if (running) currentCount += value;
101      }
102    
103      /****************************************************************************
104       *
105       * Generic counter control methods: start, stop, print etc
106       */
107    
108      /**
109       * {@inheritDoc}
110       */
111      @Override
112      protected void start() {
113        if (!Stats.gatheringStats) return;
114        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!running);
115        running = true;
116      }
117    
118      @Override
119      protected void stop() {
120        if (!Stats.gatheringStats) return;
121        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(running);
122        count[Stats.phase] = currentCount;
123        currentCount = 0;
124        running = false;
125      }
126    
127      /**
128       * The phase has changed (from GC to mutator or mutator to GC).
129       * Take action with respect to the last phase if necessary.
130       * <b>Do nothing in this case.</b>
131       *
132       * @param oldPhase The last phase
133       */
134      @Override
135      void phaseChange(int oldPhase) {
136        if (running) {
137          count[oldPhase] = currentCount;
138          currentCount = 0;
139        }
140      }
141    
142      /**
143       * {@inheritDoc}
144       * Print '0' for {@code false}, '1' for {@code true}.
145       */
146      @Override
147      protected final void printCount(int phase) {
148        if (VM.VERIFY_ASSERTIONS && mergePhases())
149          if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((phase | 1) == (phase + 1));
150        if (mergePhases())
151          printValue(count[phase] + count[phase + 1]);
152        else
153          printValue(count[phase]);
154      }
155    
156      /**
157       * Print the current value for this counter (mid-phase)
158       */
159      public final void printCurrent() {
160        printValue(currentCount);
161      }
162    
163      @Override
164      public final void printTotal() {
165        long total = 0;
166        for (int p = 0; p <= Stats.phase; p++) {
167          total += count[p];
168        }
169        printValue(total);
170      }
171    
172      @Override
173      protected final void printTotal(boolean mutator) {
174        long total = 0;
175        for (int p = (mutator) ? 0 : 1; p <= Stats.phase; p += 2) {
176          total += count[p];
177        }
178        printValue(total);
179      }
180    
181      @Override
182      protected final void printMin(boolean mutator) {
183        int p = (mutator) ? 0 : 1;
184        long min = count[p];
185        for (; p < Stats.phase; p += 2) {
186          if (count[p] < min) min = count[p];
187        }
188        printValue(min);
189      }
190    
191      @Override
192      protected final void printMax(boolean mutator) {
193        int p = (mutator) ? 0 : 1;
194        long max = count[p];
195        for (; p < Stats.phase; p += 2) {
196          if (count[p] > max) max = count[p];
197        }
198        printValue(max);
199      }
200    
201      /**
202       * Print the given value
203       *
204       * @param value The value to be printed
205       */
206      void printValue(long value) {
207        Log.write(value);
208      }
209    
210      @Override
211      public void printLast() {
212        if (Stats.phase > 0) printCount(Stats.phase - 1);
213      }
214    }