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.semispace.gctrace;
014
015import static org.mmtk.utility.Constants.*;
016
017import org.mmtk.plan.semispace.SSMutator;
018import org.mmtk.plan.*;
019import org.mmtk.utility.TraceGenerator;
020import org.mmtk.vm.VM;
021
022import org.vmmagic.unboxed.*;
023import org.vmmagic.pragma.*;
024
025/**
026 * This class implements <i>per-mutator thread</i> behavior and state for the
027 * <i>GCTrace</i> plan, which implements a GC tracing algorithm.<p>
028 *
029 * Specifically, this class defines <i>SS</i> mutator-time allocation, write
030 * barriers, and per-mutator collection semantics.<p>
031 *
032 * See {@link GCTrace} for an overview of the GC trace algorithm.
033 *
034 * @see SSMutator
035 * @see GCTrace
036 * @see GCTraceCollector
037 * @see org.mmtk.plan.StopTheWorldMutator
038 * @see org.mmtk.plan.MutatorContext
039 */
040@Uninterruptible public class GCTraceMutator extends SSMutator {
041
042  /****************************************************************************
043   *
044   * Mutator-time allocation
045   */
046
047  /**
048   * {@inheritDoc}
049   */
050  @Override
051  @Inline
052  public final void postAlloc(ObjectReference object, ObjectReference typeRef,
053      int bytes, int allocator) {
054    /* Make the trace generator aware of the new object. */
055    TraceGenerator.addTraceObject(object, allocator);
056
057    super.postAlloc(object, typeRef, bytes, allocator);
058
059    /* Now have the trace process aware of the new allocation. */
060    GCTrace.traceInducedGC = TraceGenerator.MERLIN_ANALYSIS;
061    TraceGenerator.traceAlloc(allocator == GCTrace.ALLOC_IMMORTAL, object, typeRef, bytes);
062    GCTrace.traceInducedGC = false;
063  }
064
065
066  /****************************************************************************
067   *
068   * Write barrier.
069   */
070
071  /**
072   * {@inheritDoc}<p>
073   *
074   * In this case, we remember the address of the source of the
075   * pointer if the new reference points into the nursery from
076   * non-nursery space.
077   */
078  @Override
079  @Inline
080  public final void objectReferenceWrite(ObjectReference src, Address slot,
081      ObjectReference tgt, Word metaDataA,
082      Word metaDataB, int mode) {
083    TraceGenerator.processPointerUpdate(mode == INSTANCE_FIELD,
084        src, slot, tgt);
085    VM.barriers.objectReferenceWrite(src, tgt, metaDataA, metaDataB, mode);
086  }
087
088  @Override
089  @Inline
090  public boolean objectReferenceTryCompareAndSwap(ObjectReference src, Address slot,
091      ObjectReference old, ObjectReference tgt, Word metaDataA,
092      Word metaDataB, int mode) {
093    boolean result = VM.barriers.objectReferenceTryCompareAndSwap(src, old, tgt, metaDataA, metaDataB, mode);
094    if (result) {
095      TraceGenerator.processPointerUpdate(mode == INSTANCE_FIELD, src, slot, tgt);
096    }
097    return result;
098  }
099
100  /**
101   * {@inheritDoc}<p>
102   *
103   * @param src The source of the values to be copied
104   * @param srcOffset The offset of the first source address, in
105   * bytes, relative to <code>src</code> (in principle, this could be
106   * negative).
107   * @param dst The mutated object, i.e. the destination of the copy.
108   * @param dstOffset The offset of the first destination address, in
109   * bytes relative to <code>tgt</code> (in principle, this could be
110   * negative).
111   * @param bytes The size of the region being copied, in bytes.
112   * @return True if the update was performed by the barrier, false if
113   * left to the caller (always false in this case).
114   */
115  @Override
116  public boolean objectReferenceBulkCopy(ObjectReference src, Offset srcOffset,
117      ObjectReference dst, Offset dstOffset, int bytes) {
118    /* These names seem backwards, but are defined to be compatable with the
119     * previous writeBarrier method. */
120    Address slot = dst.toAddress().plus(dstOffset);
121    Address tgtLoc = src.toAddress().plus(srcOffset);
122    for (int i = 0; i < bytes; i += BYTES_IN_ADDRESS) {
123      ObjectReference tgt = tgtLoc.loadObjectReference();
124      TraceGenerator.processPointerUpdate(false, dst, slot, tgt);
125      slot = slot.plus(BYTES_IN_ADDRESS);
126      tgtLoc = tgtLoc.plus(BYTES_IN_ADDRESS);
127    }
128    return false;
129  }
130
131  /****************************************************************************
132   *
133   * Collection
134   */
135
136  /**
137   * {@inheritDoc}
138   */
139  @Override
140  public void collectionPhase(short phaseId, boolean primary) {
141    if (!GCTrace.traceInducedGC ||
142        (phaseId != StopTheWorld.PREPARE) &&
143        (phaseId != StopTheWorld.RELEASE)) {
144      // Delegate up.
145      super.collectionPhase(phaseId, primary);
146    }
147  }
148}