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.plan.generational;
014    
015    import org.mmtk.plan.*;
016    import org.mmtk.policy.LargeObjectLocal;
017    import org.mmtk.utility.deque.*;
018    
019    import org.mmtk.vm.VM;
020    
021    import org.vmmagic.pragma.*;
022    
023    /**
024     * This abstract class implements <i>per-collector thread</i>
025     * behavior and state for <i>generational copying collectors</i>.<p>
026     *
027     * Specifically, this class defines nursery collection behavior (through
028     * <code>nurseryTrace</code> and the <code>collectionPhase</code> method).
029     * Per-collector thread remset consumers are instantiated here (used by
030     * sub-classes).
031     *
032     * @see Gen
033     * @see GenMutator
034     * @see StopTheWorldCollector
035     * @see CollectorContext
036     */
037    @Uninterruptible public abstract class GenCollector extends StopTheWorldCollector {
038    
039      /*****************************************************************************
040       * Instance fields
041       */
042    
043      /**
044       *
045       */
046      protected final GenNurseryTraceLocal nurseryTrace;
047    
048      protected final LargeObjectLocal los;
049    
050      // remembered set consumers
051      protected final ObjectReferenceDeque modbuf;
052      protected final AddressDeque remset;
053      protected final AddressPairDeque arrayRemset;
054    
055      /****************************************************************************
056       *
057       * Initialization
058       */
059    
060      /**
061       * Constructor
062       * <p>
063       * Note that the collector is a consumer of remsets, while the
064       * mutator is a producer.  The <code>GenMutator</code> class is
065       * responsible for construction of the WriteBuffer (producer).
066       * @see GenMutator
067       */
068      public GenCollector() {
069        los = new LargeObjectLocal(Plan.loSpace);
070        arrayRemset = new AddressPairDeque(global().arrayRemsetPool);
071        remset = new AddressDeque("remset", global().remsetPool);
072        modbuf = new ObjectReferenceDeque("modbuf", global().modbufPool);
073        nurseryTrace = new GenNurseryTraceLocal(global().nurseryTrace, this);
074      }
075    
076      /****************************************************************************
077       *
078       * Collection
079       */
080    
081      /**
082       * {@inheritDoc}
083       */
084      @Override
085      @NoInline
086      public void collectionPhase(short phaseId, boolean primary) {
087    
088        if (phaseId == Gen.PREPARE) {
089          los.prepare(true);
090          global().arrayRemsetPool.prepareNonBlocking();
091          global().remsetPool.prepareNonBlocking();
092          global().modbufPool.prepareNonBlocking();
093          nurseryTrace.prepare();
094          return;
095        }
096    
097        if (phaseId == StopTheWorld.ROOTS) {
098          VM.scanning.computeGlobalRoots(getCurrentTrace());
099          if (!Gen.USE_NON_HEAP_OBJECT_REFERENCE_WRITE_BARRIER || global().traceFullHeap()) {
100            VM.scanning.computeStaticRoots(getCurrentTrace());
101          }
102          if (Plan.SCAN_BOOT_IMAGE && global().traceFullHeap()) {
103            VM.scanning.computeBootImageRoots(getCurrentTrace());
104          }
105          return;
106        }
107    
108        if (phaseId == Gen.CLOSURE) {
109          if (!global().gcFullHeap) {
110            nurseryTrace.completeTrace();
111          }
112          return;
113        }
114    
115        if (phaseId == Gen.RELEASE) {
116          los.release(true);
117          if (!global().traceFullHeap()) {
118            nurseryTrace.release();
119            global().arrayRemsetPool.reset();
120            global().remsetPool.reset();
121            global().modbufPool.reset();
122          }
123          return;
124        }
125    
126        super.collectionPhase(phaseId, primary);
127      }
128    
129      /****************************************************************************
130       *
131       * Miscellaneous
132       */
133    
134      /** @return The active global plan as a <code>Gen</code> instance. */
135      @Inline
136      private static Gen global() {
137        return (Gen) VM.activePlan.global();
138      }
139    
140      @Override
141      public final TraceLocal getCurrentTrace() {
142        if (global().traceFullHeap()) return getFullHeapTrace();
143        return nurseryTrace;
144      }
145    
146      /** @return The trace to use when collecting the mature space */
147      public abstract TraceLocal getFullHeapTrace();
148    
149    }