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.plan.markcompact;
014    
015    import org.mmtk.plan.TraceLocal;
016    import org.mmtk.plan.Trace;
017    import org.mmtk.policy.MarkCompactSpace;
018    import org.mmtk.policy.Space;
019    import org.mmtk.vm.VM;
020    
021    import org.vmmagic.pragma.*;
022    import org.vmmagic.unboxed.*;
023    
024    /**
025     * This class implments the thread-local functionality for a transitive
026     * closure over a mark-compact space during the initial marking phase.
027     */
028    @Uninterruptible
029    public final class MCMarkTraceLocal extends TraceLocal {
030      /**
031       * Constructor
032       */
033      public MCMarkTraceLocal(Trace trace) {
034        super(MC.SCAN_MARK, trace);
035      }
036    
037      /****************************************************************************
038       *
039       * Externally visible Object processing and tracing
040       */
041    
042      /**
043       * Is the specified object live?
044       *
045       * @param object The object.
046       * @return True if the object is live.
047       */
048      public boolean isLive(ObjectReference object) {
049        if (object.isNull()) return false;
050        if (Space.isInSpace(MC.MARK_COMPACT, object)) {
051          return MC.mcSpace.isLive(object);
052        }
053        return super.isLive(object);
054      }
055    
056      /**
057       * This method is the core method during the trace of the object graph.
058       * The role of this method is to:
059       *
060       * 1. Ensure the traced object is not collected.
061       * 2. If this is the first visit to the object enqueue it to be scanned.
062       * 3. Return the forwarded reference to the object.
063       *
064       * In this instance, we refer objects in the mark-sweep space to the
065       * msSpace for tracing, and defer to the superclass for all others.
066       *
067       * @param object The object to be traced.
068       * @return The new reference to the same object instance.
069       */
070      @Inline
071      public ObjectReference traceObject(ObjectReference object) {
072        if (object.isNull()) return object;
073        if (Space.isInSpace(MC.MARK_COMPACT, object))
074          return MC.mcSpace.traceMarkObject(this, object);
075        return super.traceObject(object);
076      }
077    
078      /**
079       * Ensure that this object will not move for the rest of the GC.
080       *
081       * @param object The object that must not move
082       * @return The new object, guaranteed stable for the rest of the GC.
083       */
084      @Inline
085      public ObjectReference precopyObject(ObjectReference object) {
086        if (Space.isInSpace(MC.MARK_COMPACT, object)) {
087          if (MarkCompactSpace.testAndMark(object)) {
088            // TODO: If precopy returns many different objects, this will cause a leak.
089            // Currently, Jikes RVM does not require many objects to be precopied.
090            ObjectReference newObject = VM.objectModel.copy(object, MC.ALLOC_IMMORTAL);
091            MarkCompactSpace.setForwardingPointer(object, newObject);
092            processNode(newObject);
093            return newObject;
094          }
095          // Somebody else got to it first
096          while (MarkCompactSpace.getForwardingPointer(object).isNull());
097          return MarkCompactSpace.getForwardingPointer(object);
098        }
099        return super.precopyObject(object);
100      }
101    
102      /**
103       * Will this object move from this point on, during the current trace ?
104       *
105       * @param object The object to query.
106       * @return True if the object will not move.
107       */
108      public boolean willNotMoveInCurrentCollection(ObjectReference object) {
109        // All objects in the MC space may move
110        return !Space.isInSpace(MC.MARK_COMPACT, object);
111      }
112    
113    }