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 }