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      protected final GenNurseryTraceLocal nurseryTrace;
044    
045      protected final LargeObjectLocal los;
046    
047      // remembered set consumers
048      protected final ObjectReferenceDeque modbuf;
049      protected final AddressDeque remset;
050      protected final AddressPairDeque arrayRemset;
051    
052      /****************************************************************************
053       *
054       * Initialization
055       */
056    
057      /**
058       * Constructor
059       *
060       * Note that the collector is a consumer of remsets, while the
061       * mutator is a producer.  The <code>GenMutator</code> class is
062       * responsible for construction of the WriteBuffer (producer).
063       * @see GenMutator
064       */
065      public GenCollector() {
066        los = new LargeObjectLocal(Plan.loSpace);
067        arrayRemset = new AddressPairDeque(global().arrayRemsetPool);
068        remset = new AddressDeque("remset", global().remsetPool);
069        modbuf = new ObjectReferenceDeque("modbuf", global().modbufPool);
070        nurseryTrace = new GenNurseryTraceLocal(global().nurseryTrace, this);
071      }
072    
073      /****************************************************************************
074       *
075       * Collection
076       */
077    
078      /**
079       * Perform a per-collector collection phase.
080       *
081       * @param phaseId The collection phase to perform
082       * @param primary Use this thread for single-threaded local activities.
083       */
084      @NoInline
085      public void collectionPhase(short phaseId, boolean primary) {
086    
087        if (phaseId == Gen.PREPARE) {
088          los.prepare(true);
089          global().arrayRemsetPool.prepareNonBlocking();
090          global().remsetPool.prepareNonBlocking();
091          global().modbufPool.prepareNonBlocking();
092          nurseryTrace.prepare();
093          return;
094        }
095    
096        if (phaseId == StopTheWorld.ROOTS) {
097          VM.scanning.computeGlobalRoots(getCurrentTrace());
098          if (!Gen.USE_NON_HEAP_OBJECT_REFERENCE_WRITE_BARRIER || global().traceFullHeap()) {
099            VM.scanning.computeStaticRoots(getCurrentTrace());
100          }
101          if (Plan.SCAN_BOOT_IMAGE && global().traceFullHeap()) {
102            VM.scanning.computeBootImageRoots(getCurrentTrace());
103          }
104          return;
105        }
106    
107        if (phaseId == Gen.CLOSURE) {
108          if (!global().gcFullHeap) {
109            nurseryTrace.completeTrace();
110          }
111          return;
112        }
113    
114        if (phaseId == Gen.RELEASE) {
115          los.release(true);
116          if (!global().traceFullHeap()) {
117            nurseryTrace.release();
118            global().arrayRemsetPool.reset();
119            global().remsetPool.reset();
120            global().modbufPool.reset();
121          }
122          return;
123        }
124    
125        super.collectionPhase(phaseId, primary);
126      }
127    
128      /****************************************************************************
129       *
130       * Miscellaneous
131       */
132    
133      /** @return The active global plan as a <code>Gen</code> instance. */
134      @Inline
135      private static Gen global() {
136        return (Gen) VM.activePlan.global();
137      }
138    
139      public final TraceLocal getCurrentTrace() {
140        if (global().traceFullHeap()) return getFullHeapTrace();
141        return nurseryTrace;
142      }
143    
144      /** @return The trace to use when collecting the mature space */
145      public abstract TraceLocal getFullHeapTrace();
146    
147    }