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.generational.immix;
014
015import org.mmtk.plan.Plan;
016import org.mmtk.plan.TraceLocal;
017import org.mmtk.plan.generational.*;
018import org.mmtk.policy.Space;
019import org.mmtk.utility.HeaderByte;
020import org.mmtk.utility.alloc.Allocator;
021import org.mmtk.utility.alloc.ImmixAllocator;
022import org.mmtk.utility.statistics.Stats;
023
024import org.mmtk.vm.VM;
025
026import org.vmmagic.pragma.*;
027import org.vmmagic.unboxed.*;
028
029/**
030 * This class implements <i>per-collector thread</i> behavior and state for
031 * the <code>GenImmix</code> two-generational copying collector.<p>
032 *
033 * Specifically, this class defines semantics specific to the collection of
034 * the copy generation (<code>GenCollector</code> defines nursery semantics).
035 * In particular the copy space allocator is defined (for collection-time
036 * allocation into the copy space), and the copy space per-collector thread
037 * collection time semantics are defined.<p>
038 *
039 * @see GenImmix for a description of the <code>GenImmix</code> algorithm.
040 *
041 * @see GenImmix
042 * @see GenImmixMutator
043 * @see GenCollector
044 * @see org.mmtk.plan.StopTheWorldCollector
045 * @see org.mmtk.plan.CollectorContext
046 */
047@Uninterruptible
048public class GenImmixCollector extends GenCollector {
049
050  /*****************************************************************************
051   *
052   * Instance fields
053   */
054
055  /**
056   *
057   */
058  private final GenImmixMatureTraceLocal matureTrace = new GenImmixMatureTraceLocal(global().matureTrace, this);
059  private final GenImmixMatureDefragTraceLocal defragTrace = new GenImmixMatureDefragTraceLocal(global().matureTrace, this);
060
061  private final org.mmtk.policy.immix.CollectorLocal immix = new org.mmtk.policy.immix.CollectorLocal(GenImmix.immixSpace);
062
063  private final ImmixAllocator copy = new ImmixAllocator(GenImmix.immixSpace, true, false);
064  private final ImmixAllocator defragCopy = new ImmixAllocator(GenImmix.immixSpace, true, true);
065
066  /****************************************************************************
067   *
068   * Collection-time allocation
069   */
070
071  /**
072   * {@inheritDoc}
073   */
074  @Override
075  @Inline
076  public final Address allocCopy(ObjectReference original, int bytes,
077                                 int align, int offset, int allocator) {
078
079    if (Stats.GATHER_MARK_CONS_STATS) {
080      if (Space.isInSpace(GenImmix.NURSERY, original)) GenImmix.nurseryMark.inc(bytes);
081    }
082    if (allocator == Plan.ALLOC_LOS) {
083      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES);
084      return los.alloc(bytes, align, offset);
085    } else {
086      if (VM.VERIFY_ASSERTIONS) {
087        VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES);
088        if (GenImmix.immixSpace.inImmixCollection())
089          VM.assertions._assert(allocator == GenImmix.ALLOC_MATURE_MAJORGC);
090        else
091          VM.assertions._assert(allocator == GenImmix.ALLOC_MATURE_MINORGC);
092      }
093      if (GenImmix.immixSpace.inImmixDefragCollection()) {
094        return defragCopy.alloc(bytes, align, offset);
095      } else
096        return copy.alloc(bytes, align, offset);
097    }
098  }
099
100  @Override
101  @Inline
102  public final void postCopy(ObjectReference object, ObjectReference typeRef,
103      int bytes, int allocator) {
104    if (allocator == Plan.ALLOC_LOS)
105      Plan.loSpace.initializeHeader(object, false);
106    else {
107      if (VM.VERIFY_ASSERTIONS) {
108        VM.assertions._assert((!GenImmix.immixSpace.inImmixCollection() && allocator == GenImmix.ALLOC_MATURE_MINORGC) ||
109            (GenImmix.immixSpace.inImmixCollection() && allocator == GenImmix.ALLOC_MATURE_MAJORGC));
110      }
111      GenImmix.immixSpace.postCopy(object, bytes, allocator == GenImmix.ALLOC_MATURE_MAJORGC);
112    }
113    if (Gen.USE_OBJECT_BARRIER)
114      HeaderByte.markAsUnlogged(object);
115  }
116
117  /*****************************************************************************
118   *
119   * Collection
120   */
121
122  /**
123   * {@inheritDoc}
124   */
125  @Override
126  @Inline
127  public void collectionPhase(short phaseId, boolean primary) {
128    TraceLocal trace = GenImmix.immixSpace.inImmixDefragCollection() ? defragTrace : matureTrace;
129
130    if (global().traceFullHeap()) {
131      if (phaseId == GenImmix.PREPARE) {
132        super.collectionPhase(phaseId, primary);
133        trace.prepare();
134        copy.reset();
135        if (global().gcFullHeap) {
136          immix.prepare(true);
137          defragCopy.reset();
138        }
139        return;
140      }
141
142      if (phaseId == GenImmix.CLOSURE) {
143        trace.completeTrace();
144        return;
145      }
146
147      if (phaseId == GenImmix.RELEASE) {
148        trace.release();
149        if (global().gcFullHeap) {
150          immix.release(true);
151          copy.reset();
152        }
153        super.collectionPhase(phaseId, primary);
154        return;
155      }
156    }
157
158    super.collectionPhase(phaseId, primary);
159  }
160
161  @Override
162  @Inline
163  public final TraceLocal getFullHeapTrace() {
164    return GenImmix.immixSpace.inImmixDefragCollection() ? defragTrace : matureTrace;
165  }
166
167  /****************************************************************************
168   *
169   * Miscellaneous
170   */
171
172  /** @return The active global plan as a <code>GenImmix</code> instance. */
173  @Inline
174  private static GenImmix global() {
175    return (GenImmix) VM.activePlan.global();
176  }
177}