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.immix;
014
015import org.mmtk.plan.*;
016import org.mmtk.policy.ImmortalLocal;
017import org.mmtk.policy.immix.CollectorLocal;
018import org.mmtk.utility.alloc.BumpPointer;
019import org.mmtk.utility.alloc.ImmixAllocator;
020import org.mmtk.vm.VM;
021
022import org.vmmagic.pragma.*;
023import org.vmmagic.unboxed.Address;
024import org.vmmagic.unboxed.ObjectReference;
025
026/**
027 * This class implements <i>per-collector thread</i> behavior
028 * and state for the <i>Immix</i> plan, which implements a full-heap
029 * immix collector.<p>
030 *
031 * Specifically, this class defines <i>Immix</i> collection behavior
032 * (through <code>fastTrace</code> and the <code>collectionPhase</code>
033 * method).<p>
034 *
035 * @see Immix for an overview of the immix algorithm.<p>
036 *
037 * FIXME The SegregatedFreeList class (and its decendents such as
038 * MarkSweepLocal) does not properly separate mutator and collector
039 * behaviors, so the immix field below should really not exist in
040 * this class as there is no collection-time allocation in this
041 * collector.
042 *
043 * @see Immix
044 * @see org.mmtk.policy.immix.MutatorLocal
045 * @see StopTheWorldCollector
046 * @see CollectorContext
047 * @see Phase
048 */
049@Uninterruptible
050public class ImmixCollector extends StopTheWorldCollector {
051
052  /****************************************************************************
053   * Instance fields
054   */
055
056   /**
057    *
058    */
059   protected ImmixTraceLocal fastTrace;
060   protected ImmixDefragTraceLocal defragTrace;
061   protected CollectorLocal immix;
062   protected final ImmixAllocator copy;
063   protected final BumpPointer immortal;
064   protected TraceLocal currentTrace;
065
066  /****************************************************************************
067   * Initialization
068   */
069
070  /**
071   * Constructor
072   */
073  public ImmixCollector() {
074    fastTrace = new ImmixTraceLocal(global().immixTrace, null);
075    defragTrace = new ImmixDefragTraceLocal(global().immixTrace, null);
076    immix = new CollectorLocal(Immix.immixSpace);
077    copy = new ImmixAllocator(Immix.immixSpace, true, true);
078    immortal = new ImmortalLocal(Plan.immortalSpace);
079  }
080
081 /****************************************************************************
082  *
083  * Collection-time allocation
084  */
085
086  /**
087   * {@inheritDoc}
088   */
089  @Override
090  @Inline
091  public Address allocCopy(ObjectReference original, int bytes,
092      int align, int offset, int allocator) {
093    if (VM.VERIFY_ASSERTIONS) {
094      VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES);
095      VM.assertions._assert(allocator == Immix.ALLOC_DEFAULT);
096    }
097    return copy.alloc(bytes, align, offset);
098  }
099
100  @Override
101  @Inline
102  public void postCopy(ObjectReference object, ObjectReference typeRef,
103      int bytes, int allocator) {
104    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(allocator == Immix.ALLOC_DEFAULT);
105    Immix.immixSpace.postCopy(object, bytes, true);
106
107    if (VM.VERIFY_ASSERTIONS) {
108      VM.assertions._assert(getCurrentTrace().isLive(object));
109      VM.assertions._assert(getCurrentTrace().willNotMoveInCurrentCollection(object));
110    }
111  }
112
113  /****************************************************************************
114   *
115   * Collection
116   */
117
118  /**
119   * {@inheritDoc}
120   */
121  @Override
122  @Inline
123  public void collectionPhase(short phaseId, boolean primary) {
124
125    if (phaseId == Immix.PREPARE) {
126      super.collectionPhase(phaseId, primary);
127      currentTrace = Immix.immixSpace.inImmixDefragCollection() ? defragTrace : fastTrace;
128      immix.prepare(true);
129      currentTrace.prepare();
130      copy.reset();
131      return;
132    }
133
134    if (phaseId == Immix.CLOSURE) {
135      currentTrace.completeTrace();
136      return;
137    }
138
139    if (phaseId == Immix.RELEASE) {
140      currentTrace.release();
141      immix.release(true);
142      super.collectionPhase(phaseId, primary);
143      return;
144    }
145
146    super.collectionPhase(phaseId, primary);
147  }
148
149  /****************************************************************************
150   *
151   * Miscellaneous
152   */
153
154  /** @return The active global plan as an <code>Immix</code> instance. */
155  @Inline
156  private static Immix global() {
157    return (Immix) VM.activePlan.global();
158  }
159
160  /** @return The current fastTrace instance. */
161  @Override
162  @Inline
163  public final TraceLocal getCurrentTrace() {
164    return currentTrace;
165  }
166}