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.generational;
014
015import static org.mmtk.utility.Constants.BYTES_IN_ADDRESS;
016
017import org.mmtk.plan.TraceLocal;
018import org.mmtk.plan.Trace;
019import org.mmtk.utility.HeaderByte;
020import org.mmtk.utility.deque.*;
021import org.mmtk.vm.VM;
022
023import org.vmmagic.pragma.*;
024import org.vmmagic.unboxed.*;
025
026/**
027 * This class implements the core functionality for a transitive
028 * closure over the heap graph.
029 */
030@Uninterruptible
031public final class GenNurseryTraceLocal extends TraceLocal {
032
033  /****************************************************************************
034   *
035   * Instance fields.
036   */
037
038  /**
039   *
040   */
041  private final ObjectReferenceDeque modbuf;
042  private final AddressDeque remset;
043  private final AddressPairDeque arrayRemset;
044
045  /**
046   * @param trace the global trace class to use
047   * @param plan the state of the generational collector
048   */
049  public GenNurseryTraceLocal(Trace trace, GenCollector plan) {
050    super(Gen.SCAN_NURSERY, trace);
051    this.modbuf = plan.modbuf;
052    this.remset = plan.remset;
053    this.arrayRemset = plan.arrayRemset;
054  }
055
056  /****************************************************************************
057   *
058   * Externally visible Object processing and tracing
059   */
060
061  /**
062   * {@inheritDoc}
063   */
064  @Override
065  public boolean isLive(ObjectReference object) {
066    if (object.isNull()) return false;
067    if (Gen.inNursery(object)) {
068      return Gen.nurserySpace.isLive(object);
069    }
070    /* During a nursery trace, all objects not in the nursery are considered alive */
071    return true;
072  }
073
074  @Override
075  @Inline
076  public ObjectReference traceObject(ObjectReference object) {
077    if (Gen.inNursery(object)) {
078      return Gen.nurserySpace.traceObject(this, object, Gen.ALLOC_MATURE_MINORGC);
079    }
080    return object;
081  }
082
083  /**
084   * Process any remembered set entries.
085   */
086  @Override
087  @Inline
088  protected void processRememberedSets() {
089    logMessage(5, "processing modbuf");
090    ObjectReference obj;
091    while (!(obj = modbuf.pop()).isNull()) {
092      if (VM.DEBUG) VM.debugging.modbufEntry(obj);
093      HeaderByte.markAsUnlogged(obj);
094      scanObject(obj);
095    }
096    logMessage(5, "processing remset");
097    while (!remset.isEmpty()) {
098      Address loc = remset.pop();
099      if (VM.DEBUG) VM.debugging.remsetEntry(loc);
100      processRootEdge(loc, false);
101    }
102    logMessage(5, "processing array remset");
103    arrayRemset.flushLocal();
104    while (!arrayRemset.isEmpty()) {
105      Address start = arrayRemset.pop1();
106      Address guard = arrayRemset.pop2();
107      if (VM.DEBUG) VM.debugging.arrayRemsetEntry(start,guard);
108      while (start.LT(guard)) {
109        processRootEdge(start, false);
110        start = start.plus(BYTES_IN_ADDRESS);
111      }
112    }
113  }
114
115  /**
116   * Will the object move from now on during the collection.
117   *
118   * @param object The object to query.
119   * @return {@code true} if the object is guaranteed not to move.
120   */
121  @Override
122  public boolean willNotMoveInCurrentCollection(ObjectReference object) {
123    if (object.isNull()) return false;
124    return !Gen.inNursery(object);
125  }
126
127}