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.semispace.gctrace;
014    
015    import org.mmtk.plan.semispace.SSMutator;
016    import org.mmtk.plan.*;
017    import org.mmtk.utility.TraceGenerator;
018    import org.mmtk.vm.VM;
019    
020    import org.vmmagic.unboxed.*;
021    import org.vmmagic.pragma.*;
022    
023    /**
024     * This class implements <i>per-mutator thread</i> behavior and state for the
025     * <i>GCTrace</i> plan, which implements a GC tracing algorithm.<p>
026     *
027     * Specifically, this class defines <i>SS</i> mutator-time allocation, write
028     * barriers, and per-mutator collection semantics.<p>
029     *
030     * See {@link GCTrace} for an overview of the GC trace algorithm.<p>
031     *
032     * @see SSMutator
033     * @see GCTrace
034     * @see GCTraceCollector
035     * @see org.mmtk.plan.StopTheWorldMutator
036     * @see org.mmtk.plan.MutatorContext
037     */
038    @Uninterruptible public class GCTraceMutator extends SSMutator {
039    
040      /****************************************************************************
041       *
042       * Mutator-time allocation
043       */
044    
045      /**
046       * Perform post-allocation actions.  For many allocators none are
047       * required.
048       *
049       * @param object The newly allocated object
050       * @param typeRef the type reference for the instance being created
051       * @param bytes The size of the space to be allocated (in bytes)
052       * @param allocator The allocator number to be used for this allocation
053       */
054      @Inline
055      public final void postAlloc(ObjectReference object, ObjectReference typeRef,
056          int bytes, int allocator) {
057        /* Make the trace generator aware of the new object. */
058        TraceGenerator.addTraceObject(object, allocator);
059    
060        super.postAlloc(object, typeRef, bytes, allocator);
061    
062        /* Now have the trace process aware of the new allocation. */
063        GCTrace.traceInducedGC = TraceGenerator.MERLIN_ANALYSIS;
064        TraceGenerator.traceAlloc(allocator == GCTrace.ALLOC_IMMORTAL, object, typeRef, bytes);
065        GCTrace.traceInducedGC = false;
066      }
067    
068    
069      /****************************************************************************
070       *
071       * Write barrier.
072       */
073    
074      /**
075       * A new reference is about to be created.  Take appropriate write
076       * barrier actions.<p>
077       *
078       * In this case, we remember the address of the source of the
079       * pointer if the new reference points into the nursery from
080       * non-nursery space.
081       *
082       * @param src The object into which the new reference will be stored
083       * @param slot The address into which the new reference will be
084       * stored.
085       * @param tgt The target of the new reference
086       * @param metaDataA A value that assists the host VM in creating a store
087       * @param metaDataB A value that assists the host VM in creating a store
088       * being modified
089       * @param mode The mode of the store (eg putfield, putstatic etc)
090       */
091      @Inline
092      public final void objectReferenceWrite(ObjectReference src, Address slot,
093          ObjectReference tgt, Word metaDataA,
094          Word metaDataB, int mode) {
095        TraceGenerator.processPointerUpdate(mode == INSTANCE_FIELD,
096            src, slot, tgt);
097        VM.barriers.objectReferenceWrite(src, tgt, metaDataA, metaDataB, mode);
098      }
099    
100      /**
101       * Attempt to atomically exchange the value in the given slot
102       * with the passed replacement value. If a new reference is
103       * created, we must then take appropriate write barrier actions.<p>
104       *
105       * <b>By default do nothing, override if appropriate.</b>
106       *
107       * @param src The object into which the new reference will be stored
108       * @param slot The address into which the new reference will be
109       * stored.
110       * @param old The old reference to be swapped out
111       * @param tgt The target of the new reference
112       * @param metaDataA A value that assists the host VM in creating a store
113       * @param metaDataB A value that assists the host VM in creating a store
114       * @param mode The context in which the store occured
115       * @return True if the swap was successful.
116       */
117      @Inline
118      public boolean objectReferenceTryCompareAndSwap(ObjectReference src, Address slot,
119          ObjectReference old, ObjectReference tgt, Word metaDataA,
120          Word metaDataB, int mode) {
121        boolean result = VM.barriers.objectReferenceTryCompareAndSwap(src, old, tgt, metaDataA, metaDataB, mode);
122        if (result) {
123          TraceGenerator.processPointerUpdate(mode == INSTANCE_FIELD, src, slot, tgt);
124        }
125        return result;
126      }
127    
128      /**
129       * A number of references are about to be copied from object
130       * <code>src</code> to object <code>dst</code> (as in an array
131       * copy).  Thus, <code>dst</code> is the mutated object.  Take
132       * appropriate write barrier actions.<p>
133       *
134       * @param src The source of the values to be copied
135       * @param srcOffset The offset of the first source address, in
136       * bytes, relative to <code>src</code> (in principle, this could be
137       * negative).
138       * @param dst The mutated object, i.e. the destination of the copy.
139       * @param dstOffset The offset of the first destination address, in
140       * bytes relative to <code>tgt</code> (in principle, this could be
141       * negative).
142       * @param bytes The size of the region being copied, in bytes.
143       * @return True if the update was performed by the barrier, false if
144       * left to the caller (always false in this case).
145       */
146      public boolean objectReferenceBulkCopy(ObjectReference src, Offset srcOffset,
147          ObjectReference dst, Offset dstOffset, int bytes) {
148        /* These names seem backwards, but are defined to be compatable with the
149         * previous writeBarrier method. */
150        Address slot = dst.toAddress().plus(dstOffset);
151        Address tgtLoc = src.toAddress().plus(srcOffset);
152        for (int i = 0; i < bytes; i += BYTES_IN_ADDRESS) {
153          ObjectReference tgt = tgtLoc.loadObjectReference();
154          TraceGenerator.processPointerUpdate(false, dst, slot, tgt);
155          slot = slot.plus(BYTES_IN_ADDRESS);
156          tgtLoc = tgtLoc.plus(BYTES_IN_ADDRESS);
157        }
158        return false;
159      }
160    
161      /****************************************************************************
162       *
163       * Collection
164       */
165    
166      /**
167       * Perform a per-mutator collection phase.
168       *
169       * @param phaseId The collection phase to perform
170       * @param primary perform any single-threaded local activities.
171       */
172      public void collectionPhase(short phaseId, boolean primary) {
173        if (!GCTrace.traceInducedGC ||
174            (phaseId != StopTheWorld.PREPARE) &&
175            (phaseId != StopTheWorld.RELEASE)) {
176          // Delegate up.
177          super.collectionPhase(phaseId, primary);
178        }
179      }
180    }