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.immix;
014
015import static org.mmtk.policy.immix.ImmixConstants.MARK_LINE_AT_SCAN_TIME;
016
017import org.mmtk.plan.Plan;
018import org.mmtk.plan.TraceLocal;
019import org.mmtk.plan.Trace;
020import org.mmtk.policy.Space;
021import org.mmtk.utility.HeaderByte;
022import org.mmtk.utility.deque.ObjectReferenceDeque;
023import org.mmtk.vm.VM;
024
025import org.vmmagic.pragma.*;
026import 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
033public final class ImmixDefragTraceLocal extends TraceLocal {
034
035  /****************************************************************************
036  *
037  * Instance fields
038  */
039 private final ObjectReferenceDeque modBuffer;
040
041 /**
042   * Constructor
043   * @param trace the associated global trace
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 the object whose status is of interest
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}