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 */
013package org.mmtk.plan.concurrent.marksweep;
014
015import org.mmtk.plan.*;
016import org.mmtk.plan.concurrent.ConcurrentMutator;
017import org.mmtk.policy.MarkSweepLocal;
018import org.mmtk.policy.Space;
019
020import org.mmtk.utility.alloc.Allocator;
021import org.mmtk.vm.VM;
022
023import org.vmmagic.pragma.*;
024import 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
043public class CMSMutator extends ConcurrentMutator {
044
045  /****************************************************************************
046   * Instance fields
047   */
048
049  /**
050   *
051   */
052  private final MarkSweepLocal ms;
053  private final 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}