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.policy.immix;
014    
015    import static org.mmtk.policy.immix.ImmixConstants.*;
016    
017    import org.mmtk.utility.Constants;
018    import org.mmtk.vm.VM;
019    
020    import org.vmmagic.pragma.*;
021    import org.vmmagic.unboxed.Address;
022    
023    /**
024     * This class implements unsynchronized (local) elements of an
025     * immix collector.  Marking is done using both a bit in
026     * each header's object word, and a mark byte.  Sweeping is
027     * performed lazily.<p>
028     *
029     */
030    @Uninterruptible
031    public final class CollectorLocal implements Constants {
032    
033      /****************************************************************************
034       *
035       * Class variables
036       */
037    
038    
039      /****************************************************************************
040       *
041       * Instance variables
042       */
043    
044      /**
045       *
046       */
047      private final ImmixSpace immixSpace;
048      private final ChunkList chunkMap;
049      private final Defrag defrag;
050    
051    
052      /****************************************************************************
053       *
054       * Initialization
055       */
056    
057      /**
058       * Constructor
059       *
060       * @param space The mark-sweep space to which this allocator
061       * instances is bound.
062       */
063      public CollectorLocal(ImmixSpace space) {
064        immixSpace = space;
065        chunkMap = immixSpace.getChunkMap();
066        defrag = immixSpace.getDefrag();
067      }
068    
069      /****************************************************************************
070       *
071       * Collection
072       */
073    
074      /**
075       * Prepare for a collection. If paranoid, perform a sanity check.
076       */
077      public void prepare(boolean majorGC) {
078        int ordinal = VM.activePlan.collector().parallelWorkerOrdinal();
079        if (majorGC) {
080          if (immixSpace.inImmixDefragCollection()) {
081            short threshold = Defrag.defragSpillThreshold;
082            resetLineMarksAndDefragStateTable(ordinal, threshold);
083          }
084        }
085      }
086    
087      private void resetLineMarksAndDefragStateTable(int ordinal, final short threshold) {
088        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(immixSpace.inImmixDefragCollection());
089        int stride = VM.activePlan.collector().parallelWorkerCount();
090        Address chunk = chunkMap.firstChunk(ordinal, stride);
091        while (!chunk.isZero()) {
092          Chunk.resetLineMarksAndDefragStateTable(chunk, threshold);
093          chunk = chunkMap.nextChunk(chunk, ordinal, stride);
094        }
095      }
096    
097      /**
098       * Finish up after a collection.
099       *
100       * We help sweeping all the blocks in parallel.
101       */
102      public void release(boolean majorGC) {
103        sweepAllBlocks(majorGC);
104      }
105    
106      private void sweepAllBlocks(boolean majorGC) {
107        int stride = VM.activePlan.collector().parallelWorkerCount();
108        int ordinal = VM.activePlan.collector().parallelWorkerOrdinal();
109        int[] markSpillHisto = defrag.getAndZeroSpillMarkHistogram(ordinal);
110        Address chunk = chunkMap.firstChunk(ordinal, stride);
111        final byte markValue = immixSpace.lineMarkState;
112        final boolean resetMarks = majorGC && markValue == MAX_LINE_MARK_STATE;
113        while (!chunk.isZero()) {
114          Chunk.sweep(chunk, Chunk.getHighWater(chunk), immixSpace, markSpillHisto, markValue, resetMarks);
115          chunk = chunkMap.nextChunk(chunk, ordinal, stride);
116        }
117      }
118    }