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.concurrent;
014    
015    import org.mmtk.plan.*;
016    
017    import org.mmtk.vm.VM;
018    
019    import org.vmmagic.pragma.*;
020    import org.vmmagic.unboxed.*;
021    
022    /**
023     * This class implements <i>per-mutator thread</i> behavior
024     * and state for a simple whole-heap concurrent collector.
025     *
026     * @see Concurrent
027     * @see ConcurrentCollector
028     * @see StopTheWorldMutator
029     * @see MutatorContext
030     */
031    @Uninterruptible
032    public abstract class ConcurrentMutator extends SimpleMutator {
033    
034      /****************************************************************************
035       * Instance fields
036       */
037    
038      /**
039       *
040       */
041      public static boolean newMutatorBarrierActive = false;
042      protected volatile boolean barrierActive = false;
043    
044      protected ConcurrentMutator() {
045        barrierActive = newMutatorBarrierActive;
046      }
047    
048      /****************************************************************************
049       *
050       * Collection
051       */
052    
053      /**
054       * Perform a per-mutator collection phase.
055       */
056      @Override
057      @Inline
058      public void collectionPhase(short phaseId, boolean primary) {
059        if (phaseId == Concurrent.SET_BARRIER_ACTIVE) {
060          barrierActive = true;
061          return;
062        }
063    
064        if (phaseId == Concurrent.CLEAR_BARRIER_ACTIVE) {
065          barrierActive = false;
066          return;
067        }
068    
069        if (phaseId == Concurrent.FLUSH_MUTATOR) {
070          flush();
071          return;
072        }
073    
074        super.collectionPhase(phaseId, primary);
075      }
076    
077      /****************************************************************************
078      *
079      * Write and read barriers.
080      */
081    
082      /**
083       * {@inheritDoc}<p>
084       *
085       * <b>In this case we employ a Yuasa style snapshot barrier.</b>
086       *
087       */
088      @Inline
089      @Override
090      public void objectReferenceWrite(ObjectReference src, Address slot, ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) {
091        if (barrierActive) checkAndEnqueueReference(slot.loadObjectReference());
092        VM.barriers.objectReferenceWrite(src, tgt, metaDataA, metaDataB, mode);
093      }
094    
095      @Inline
096      @Override
097      public boolean objectReferenceTryCompareAndSwap(ObjectReference src, Address slot, ObjectReference old,
098                                                   ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) {
099        boolean result = VM.barriers.objectReferenceTryCompareAndSwap(src, old, tgt, metaDataA, metaDataB, mode);
100        if (barrierActive) checkAndEnqueueReference(old);
101        return result;
102      }
103    
104      /**
105       * {@inheritDoc}
106       *
107       * @param src The source of the values to be copied
108       * @param srcOffset The offset of the first source address, in
109       * bytes, relative to <code>src</code> (in principle, this could be
110       * negative).
111       * @param dst The mutated object, i.e. the destination of the copy.
112       * @param dstOffset The offset of the first destination address, in
113       * bytes relative to <code>tgt</code> (in principle, this could be
114       * negative).
115       * @param bytes The size of the region being copied, in bytes.
116       */
117      @Inline
118      @Override
119      public boolean objectReferenceBulkCopy(ObjectReference src, Offset srcOffset, ObjectReference dst, Offset dstOffset, int bytes) {
120        Address cursor = dst.toAddress().plus(dstOffset);
121        Address limit = cursor.plus(bytes);
122        while (cursor.LT(limit)) {
123          ObjectReference ref = cursor.loadObjectReference();
124          if (barrierActive) checkAndEnqueueReference(ref);
125          cursor = cursor.plus(BYTES_IN_ADDRESS);
126        }
127        return false;
128      }
129    
130      @Inline
131      @Override
132      public ObjectReference javaLangReferenceReadBarrier(ObjectReference ref) {
133        if (barrierActive) checkAndEnqueueReference(ref);
134        return ref;
135      }
136    
137      /**
138       * Process a reference that may require being enqueued as part of a concurrent
139       * collection.
140       *
141       * @param ref The reference to check.
142       */
143      protected abstract void checkAndEnqueueReference(ObjectReference ref);
144    }