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.policy;
014
015import static org.mmtk.utility.Constants.*;
016
017import org.mmtk.plan.TransitiveClosure;
018import org.mmtk.utility.heap.*;
019import org.mmtk.utility.options.Options;
020import org.mmtk.utility.ForwardingWord;
021import org.mmtk.utility.Log;
022
023import org.mmtk.vm.VM;
024
025import org.vmmagic.unboxed.*;
026import org.vmmagic.pragma.*;
027
028/**
029 * This class implements tracing functionality for a simple copying
030 * space.  Since no state needs to be held globally or locally, all
031 * methods are static.
032 */
033@Uninterruptible public final class CopySpace extends Space {
034
035  /****************************************************************************
036   *
037   * Class variables
038   */
039
040  /**
041   *
042   */
043  public static final int LOCAL_GC_BITS_REQUIRED = 2;
044  public static final int GLOBAL_GC_BITS_REQUIRED = 0;
045  public static final int GC_HEADER_WORDS_REQUIRED = 0;
046
047  private static final int META_DATA_PAGES_PER_REGION = CARD_META_PAGES_PER_REGION;
048
049
050  /****************************************************************************
051   *
052   * Instance variables
053   */
054
055  /**
056   *
057   */
058  private boolean fromSpace = true;
059
060  public boolean isFromSpace() {
061    return fromSpace;
062  }
063
064  /** fromSpace CopySpace can always move, toSpace will not move during current GC */
065  @Override
066  public boolean isMovable() {
067    return fromSpace;
068  }
069
070  /****************************************************************************
071   *
072   * Initialization
073   */
074
075  /**
076   * The caller specifies the region of virtual memory to be used for
077   * this space.  If this region conflicts with an existing space,
078   * then the constructor will fail.
079   *
080   * @param name The name of this space (used when printing error messages etc)
081   * @param fromSpace The does this instance start life as from-space
082   * (or to-space)?
083   * @param vmRequest An object describing the virtual memory requested.
084   */
085  public CopySpace(String name, boolean fromSpace, VMRequest vmRequest) {
086    this(name, fromSpace, true, vmRequest);
087  }
088
089  /**
090   * The caller specifies the region of virtual memory to be used for
091   * this space.  If this region conflicts with an existing space,
092   * then the constructor will fail.
093   *
094   * @param name The name of this space (used when printing error messages etc)
095   * @param fromSpace The does this instance start life as from-space
096   * @param zeroed if true, allocations return zeroed memory.
097   * (or to-space)?
098   * @param vmRequest An object describing the virtual memory requested.
099   */
100  public CopySpace(String name, boolean fromSpace, boolean zeroed, VMRequest vmRequest) {
101    super(name, true, false, zeroed, vmRequest);
102    this.fromSpace = fromSpace;
103    if (vmRequest.isDiscontiguous()) {
104      pr = new MonotonePageResource(this, META_DATA_PAGES_PER_REGION);
105    } else {
106      pr = new MonotonePageResource(this, start, extent, META_DATA_PAGES_PER_REGION);
107    }
108  }
109
110  /****************************************************************************
111   *
112   * Prepare and release
113   */
114
115  /**
116   * Prepare this space instance for a collection.  Set the
117   * "fromSpace" field according to whether this space is the
118   * source or target of the collection.
119   *
120   * @param fromSpace Set the fromSpace field to this value
121   */
122  public void prepare(boolean fromSpace) {
123    this.fromSpace = fromSpace;
124  }
125
126  /**
127   * Release this copy space after a collection.  This means releasing
128   * all pages associated with this (now empty) space.
129   */
130  public void release() {
131    ((MonotonePageResource) pr).reset();
132    headDiscontiguousRegion = Address.zero();
133    fromSpace = false;
134  }
135
136  /**
137   * Release an allocated page or pages.  In this case we do nothing
138   * because we only release pages enmasse.
139   *
140   * @param start The address of the start of the page or pages
141   */
142  @Override
143  @Inline
144  public void release(Address start) {
145    if (VM.VERIFY_ASSERTIONS)
146      VM.assertions._assert(false); // this policy only releases pages enmasse
147  }
148
149  /****************************************************************************
150   *
151   * Tracing and forwarding
152   */
153
154  /**
155   * Trace an object under a copying collection policy.<p>
156   *
157   * We use a tri-state algorithm to deal with races to forward
158   * the object.  The tracer must wait if the object is concurrently
159   * being forwarded by another thread.<p>
160   *
161   * If the object is already forwarded, the copy is returned.
162   * Otherwise, the object is forwarded and the copy is returned.
163   *
164   * @param trace The trace being conducted.
165   * @param object The object to be forwarded.
166   * @return The forwarded object.
167   */
168  @Override
169  @Inline
170  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
171    VM.assertions.fail("CopySpace.traceLocal called without allocator");
172    return ObjectReference.nullReference();
173  }
174
175  /**
176   * Trace an object under a copying collection policy.<p>
177   *
178   * We use a tri-state algorithm to deal with races to forward
179   * the object.  The tracer must wait if the object is concurrently
180   * being forwarded by another thread.<p>
181   *
182   * If the object is already forwarded, the copy is returned.
183   * Otherwise, the object is forwarded and the copy is returned.
184   *
185   * @param trace The trace being conducted.
186   * @param object The object to be forwarded.
187   * @param allocator The allocator to use when copying.
188   * @return The forwarded object.
189   */
190  @Inline
191  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object, int allocator) {
192    /* If the object in question is already in to-space, then do nothing */
193    if (!fromSpace) return object;
194
195    /* Try to forward the object */
196    Word forwardingWord = ForwardingWord.attemptToForward(object);
197
198    if (ForwardingWord.stateIsForwardedOrBeingForwarded(forwardingWord)) {
199      /* Somebody else got to it first. */
200
201      /* We must wait (spin) if the object is not yet fully forwarded */
202      while (ForwardingWord.stateIsBeingForwarded(forwardingWord))
203        forwardingWord = VM.objectModel.readAvailableBitsWord(object);
204
205      /* Now extract the object reference from the forwarding word and return it */
206      return ForwardingWord.extractForwardingPointer(forwardingWord);
207    } else {
208      /* We are the designated copier, so forward it and enqueue it */
209      ObjectReference newObject = VM.objectModel.copy(object, allocator);
210      ForwardingWord.setForwardingPointer(object, newObject);
211      trace.processNode(newObject); // Scan it later
212
213      if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) {
214        Log.write("C["); Log.write(object); Log.write("/");
215        Log.write(getName()); Log.write("] -> ");
216        Log.write(newObject); Log.write("/");
217        Log.write(Space.getSpaceForObject(newObject).getName());
218        Log.writeln("]");
219      }
220      return newObject;
221    }
222  }
223
224  /**
225   * Return {@code true} if this object is live in this GC
226   *
227   * @param object The object in question
228   * @return {@code true} if this object is live in this GC (has it been forwarded?)
229   */
230  @Override
231  public boolean isLive(ObjectReference object) {
232    return ForwardingWord.isForwarded(object);
233  }
234
235  @Override
236  public boolean isReachable(ObjectReference object) {
237    return !fromSpace || ForwardingWord.isForwarded(object);
238  }
239
240  /****************************************************************************
241   *
242   * Header manipulation
243   */
244
245  /**
246   * Perform any required post-allocation initialization
247   *
248   * <i>Nothing to be done in this case</i>
249   *
250   * @param object the object ref to the storage to be initialized
251   */
252   @Inline
253   public void postAlloc(ObjectReference object) {}
254
255}