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.policy;
014    
015    import org.mmtk.plan.TransitiveClosure;
016    import org.mmtk.utility.heap.*;
017    import org.mmtk.utility.options.Options;
018    import org.mmtk.utility.Constants;
019    import org.mmtk.utility.ForwardingWord;
020    import org.mmtk.utility.Log;
021    
022    import org.mmtk.vm.VM;
023    
024    import org.vmmagic.unboxed.*;
025    import org.vmmagic.pragma.*;
026    
027    /**
028     * This class implements tracing functionality for a simple copying
029     * space.  Since no state needs to be held globally or locally, all
030     * methods are static.
031     */
032    @Uninterruptible public final class CopySpace extends Space
033      implements Constants {
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) { this.fromSpace = fromSpace; }
123    
124      /**
125       * Release this copy space after a collection.  This means releasing
126       * all pages associated with this (now empty) space.
127       */
128      public void release() {
129        ((MonotonePageResource) pr).reset();
130        headDiscontiguousRegion = Address.zero();
131        fromSpace = false;
132      }
133    
134      /**
135       * Release an allocated page or pages.  In this case we do nothing
136       * because we only release pages enmasse.
137       *
138       * @param start The address of the start of the page or pages
139       */
140      @Override
141      @Inline
142      public void release(Address start) {
143        if (VM.VERIFY_ASSERTIONS)
144          VM.assertions._assert(false); // this policy only releases pages enmasse
145      }
146    
147      /****************************************************************************
148       *
149       * Tracing and forwarding
150       */
151    
152      /**
153       * Trace an object under a copying collection policy.<p>
154       *
155       * We use a tri-state algorithm to deal with races to forward
156       * the object.  The tracer must wait if the object is concurrently
157       * being forwarded by another thread.<p>
158       *
159       * If the object is already forwarded, the copy is returned.
160       * Otherwise, the object is forwarded and the copy is returned.
161       *
162       * @param trace The trace being conducted.
163       * @param object The object to be forwarded.
164       * @return The forwarded object.
165       */
166      @Override
167      @Inline
168      public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
169        VM.assertions.fail("CopySpace.traceLocal called without allocator");
170        return ObjectReference.nullReference();
171      }
172    
173      /**
174       * Trace an object under a copying collection policy.<p>
175       *
176       * We use a tri-state algorithm to deal with races to forward
177       * the object.  The tracer must wait if the object is concurrently
178       * being forwarded by another thread.<p>
179       *
180       * If the object is already forwarded, the copy is returned.
181       * Otherwise, the object is forwarded and the copy is returned.
182       *
183       * @param trace The trace being conducted.
184       * @param object The object to be forwarded.
185       * @param allocator The allocator to use when copying.
186       * @return The forwarded object.
187       */
188      @Inline
189      public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object, int allocator) {
190        /* If the object in question is already in to-space, then do nothing */
191        if (!fromSpace) return object;
192    
193        /* Try to forward the object */
194        Word forwardingWord = ForwardingWord.attemptToForward(object);
195    
196        if (ForwardingWord.stateIsForwardedOrBeingForwarded(forwardingWord)) {
197          /* Somebody else got to it first. */
198    
199          /* We must wait (spin) if the object is not yet fully forwarded */
200          while (ForwardingWord.stateIsBeingForwarded(forwardingWord))
201            forwardingWord = VM.objectModel.readAvailableBitsWord(object);
202    
203          /* Now extract the object reference from the forwarding word and return it */
204          return ForwardingWord.extractForwardingPointer(forwardingWord);
205        } else {
206          /* We are the designated copier, so forward it and enqueue it */
207          ObjectReference newObject = VM.objectModel.copy(object, allocator);
208          ForwardingWord.setForwardingPointer(object, newObject);
209          trace.processNode(newObject); // Scan it later
210    
211          if (VM.VERIFY_ASSERTIONS && Options.verbose.getValue() >= 9) {
212            Log.write("C["); Log.write(object); Log.write("/");
213            Log.write(getName()); Log.write("] -> ");
214            Log.write(newObject); Log.write("/");
215            Log.write(Space.getSpaceForObject(newObject).getName());
216            Log.writeln("]");
217          }
218          return newObject;
219        }
220      }
221    
222      /**
223       * Return {@code true} if this object is live in this GC
224       *
225       * @param object The object in question
226       * @return {@code true} if this object is live in this GC (has it been forwarded?)
227       */
228      @Override
229      public boolean isLive(ObjectReference object) {
230        return ForwardingWord.isForwarded(object);
231      }
232    
233      @Override
234      public boolean isReachable(ObjectReference object) {
235        return !fromSpace || ForwardingWord.isForwarded(object);
236      }
237    
238      /****************************************************************************
239       *
240       * Header manipulation
241       */
242    
243      /**
244       * Perform any required post-allocation initialization
245       *
246       * <i>Nothing to be done in this case</i>
247       *
248       * @param object the object ref to the storage to be initialized
249       */
250       @Inline
251       public void postAlloc(ObjectReference object) {}
252    
253    }