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.concurrent.marksweep;
014    
015    import org.mmtk.plan.*;
016    import org.mmtk.plan.concurrent.ConcurrentMutator;
017    import org.mmtk.policy.MarkSweepLocal;
018    import org.mmtk.policy.Space;
019    
020    import org.mmtk.utility.alloc.Allocator;
021    import org.mmtk.vm.VM;
022    
023    import org.vmmagic.pragma.*;
024    import org.vmmagic.unboxed.*;
025    
026    /**
027     * This class implements <i>per-mutator thread</i> behavior
028     * and state for the <i>CMS</i> plan, which implements a full-heap
029     * concurrent mark-sweep collector.<p>
030     *
031     * FIXME The SegregatedFreeList class (and its descendants such as
032     * MarkSweepLocal) does not properly separate mutator and collector
033     * behaviors, so the ms field below should really not exist in
034     * this class as there is no collection-time allocation in this
035     * collector.
036     *
037     * @see CMS
038     * @see CMSCollector
039     * @see StopTheWorldMutator
040     * @see MutatorContext
041     */
042    @Uninterruptible
043    public class CMSMutator extends ConcurrentMutator {
044    
045      /****************************************************************************
046       * Instance fields
047       */
048    
049      /**
050       *
051       */
052      private MarkSweepLocal ms;
053      private TraceWriteBuffer remset;
054    
055      /****************************************************************************
056       *
057       * Initialization
058       */
059    
060      /**
061       * Constructor
062       */
063      public CMSMutator() {
064        ms = new MarkSweepLocal(CMS.msSpace);
065        remset = new TraceWriteBuffer(global().msTrace);
066      }
067    
068      /****************************************************************************
069       *
070       * Mutator-time allocation
071       */
072    
073      /**
074       * {@inheritDoc}<p>
075       *
076       * This class handles the default allocator from the mark sweep space, and
077       * delegates everything else to the superclass.
078       */
079      @Inline
080      @Override
081      public Address alloc(int bytes, int align, int offset, int allocator, int site) {
082        if (allocator == CMS.ALLOC_DEFAULT) {
083          return ms.alloc(bytes, align, offset);
084        }
085        return super.alloc(bytes, align, offset, allocator, site);
086      }
087    
088      /**
089       * {@inheritDoc}<p>
090       *
091       * Initialize the object header for objects in the mark-sweep space,
092       * and delegate to the superclass for other objects.
093       */
094      @NoInline
095      @Override
096      public void postAlloc(ObjectReference ref, ObjectReference typeRef,
097          int bytes, int allocator) {
098        switch (allocator) {
099          case CMS.ALLOC_DEFAULT: CMS.msSpace.initializeHeader(ref, true); break;
100          default:
101            super.postAlloc(ref, typeRef, bytes, allocator);
102            break;
103        }
104      }
105    
106      @Override
107      public Allocator getAllocatorFromSpace(Space space) {
108        if (space == CMS.msSpace) return ms;
109        return super.getAllocatorFromSpace(space);
110      }
111    
112      /****************************************************************************
113       *
114       * Collection
115       */
116    
117      /**
118       * {@inheritDoc}
119       */
120      @Override
121      @Inline
122      public void collectionPhase(short phaseId, boolean primary) {
123        if (phaseId == CMS.PREPARE) {
124          super.collectionPhase(phaseId, primary);
125          ms.prepare();
126          return;
127        }
128    
129        if (phaseId == CMS.RELEASE) {
130          ms.release();
131          super.collectionPhase(phaseId, primary);
132          return;
133        }
134    
135        super.collectionPhase(phaseId, primary);
136      }
137    
138      @Override
139      public void flushRememberedSets() {
140        remset.flush();
141        ms.flush();
142      }
143    
144      /****************************************************************************
145       *
146       * Write and read barriers.
147       */
148    
149      /**
150       * {@inheritDoc}
151       */
152      @Override
153      protected void checkAndEnqueueReference(ObjectReference ref) {
154        if (ref.isNull()) return;
155        if (barrierActive) {
156          if (!ref.isNull()) {
157            if      (Space.isInSpace(CMS.MARK_SWEEP, ref)) CMS.msSpace.traceObject(remset, ref);
158            else if (Space.isInSpace(CMS.IMMORTAL,   ref)) CMS.immortalSpace.traceObject(remset, ref);
159            else if (Space.isInSpace(CMS.LOS,        ref)) CMS.loSpace.traceObject(remset, ref);
160            else if (Space.isInSpace(CMS.NON_MOVING, ref)) CMS.nonMovingSpace.traceObject(remset, ref);
161            else if (Space.isInSpace(CMS.SMALL_CODE, ref)) CMS.smallCodeSpace.traceObject(remset, ref);
162            else if (Space.isInSpace(CMS.LARGE_CODE, ref)) CMS.largeCodeSpace.traceObject(remset, ref);
163          }
164        }
165    
166        if (VM.VERIFY_ASSERTIONS) {
167          if (!ref.isNull() && !Plan.gcInProgress()) {
168            if      (Space.isInSpace(CMS.MARK_SWEEP, ref)) VM.assertions._assert(CMS.msSpace.isLive(ref));
169            else if (Space.isInSpace(CMS.IMMORTAL,   ref)) VM.assertions._assert(CMS.immortalSpace.isLive(ref));
170            else if (Space.isInSpace(CMS.LOS,        ref)) VM.assertions._assert(CMS.loSpace.isLive(ref));
171            else if (Space.isInSpace(CMS.NON_MOVING, ref)) VM.assertions._assert(CMS.nonMovingSpace.isLive(ref));
172            else if (Space.isInSpace(CMS.SMALL_CODE, ref)) VM.assertions._assert(CMS.smallCodeSpace.isLive(ref));
173            else if (Space.isInSpace(CMS.LARGE_CODE, ref)) VM.assertions._assert(CMS.largeCodeSpace.isLive(ref));
174          }
175        }
176      }
177    
178      /****************************************************************************
179       *
180       * Miscellaneous
181       */
182    
183      /** @return The active global plan as a <code>Gen</code> instance. */
184      @Inline
185      private static CMS global() {
186        return (CMS) VM.activePlan.global();
187      }
188    }