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.immix;
014    
015    import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME;
016    
017    import org.mmtk.plan.Plan;
018    import org.mmtk.plan.TraceLocal;
019    import org.mmtk.plan.Trace;
020    import org.mmtk.policy.Space;
021    import org.mmtk.utility.HeaderByte;
022    import org.mmtk.utility.deque.ObjectReferenceDeque;
023    import org.mmtk.vm.VM;
024    
025    import org.vmmagic.pragma.*;
026    import org.vmmagic.unboxed.*;
027    
028    /**
029     * This class implements the thread-local functionality for a defragmenting
030     * transitive closure over an immix space.
031     */
032    @Uninterruptible
033    public final class ImmixDefragTraceLocal extends TraceLocal {
034    
035      /****************************************************************************
036      *
037      * Instance fields
038      */
039     private final ObjectReferenceDeque modBuffer;
040    
041     /**
042       * Constructor
043       * @param trace TODO
044       * @param modBuffer TODO
045       */
046      public ImmixDefragTraceLocal(Trace trace, ObjectReferenceDeque modBuffer) {
047        super(Immix.SCAN_DEFRAG, trace);
048        this.modBuffer = modBuffer;
049      }
050    
051      /****************************************************************************
052       *
053       * Externally visible Object processing and tracing
054       */
055    
056      /**
057       * {@inheritDoc}
058       */
059      @Override
060      public boolean isLive(ObjectReference object) {
061        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection());
062        if (object.isNull()) return false;
063        if (Space.isInSpace(Immix.IMMIX, object)) {
064          return Immix.immixSpace.isLive(object);
065        }
066        return super.isLive(object);
067      }
068    
069      /**
070       * {@inheritDoc}<p>
071       *
072       * In this instance, we refer objects in the mark-sweep space to the
073       * immixSpace for tracing, and defer to the superclass for all others.
074       *
075       * @param object The object to be traced.
076       * @return The new reference to the same object instance.
077       */
078      @Override
079      @Inline
080      public ObjectReference traceObject(ObjectReference object) {
081        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection());
082        if (object.isNull()) return object;
083        if (Space.isInSpace(Immix.IMMIX, object))
084          return Immix.immixSpace.traceObject(this, object, Plan.ALLOC_DEFAULT);
085        return super.traceObject(object);
086      }
087    
088      /**
089       * Return {@code true} if this object is guaranteed not to move during this
090       * collection (i.e. this object is defintely not an unforwarded
091       * object).
092       *
093       * @param object
094       * @return {@code true} if this object is guaranteed not to move during this
095       *         collection.
096       */
097      @Override
098      public boolean willNotMoveInCurrentCollection(ObjectReference object) {
099        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection());
100        if (Space.isInSpace(Immix.IMMIX, object))
101          return Immix.immixSpace.willNotMoveThisGC(object);
102        return true;
103      }
104    
105      @Inline
106      @Override
107      protected void scanObject(ObjectReference object) {
108        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Immix.immixSpace.inImmixDefragCollection());
109        super.scanObject(object);
110        if (MARK_LINE_AT_SCAN_TIME && Space.isInSpace(Immix.IMMIX, object))
111          Immix.immixSpace.markLines(object);
112      }
113    
114      /**
115       * Process any remembered set entries.  This means enumerating the
116       * mod buffer and for each entry, marking the object as unlogged
117       * (we don't enqueue for scanning since we're doing a full heap GC).
118       */
119      @Override
120      protected void processRememberedSets() {
121        if (modBuffer != null) {
122          logMessage(5, "clearing modBuffer");
123          while (!modBuffer.isEmpty()) {
124            ObjectReference src = modBuffer.pop();
125            HeaderByte.markAsUnlogged(src);
126          }
127        }
128      }
129    }