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.stickyimmix;
014
015 import org.mmtk.plan.*;
016 import org.mmtk.plan.immix.ImmixMutator;
017
018 import org.mmtk.utility.HeaderByte;
019 import org.mmtk.utility.deque.ObjectReferenceDeque;
020 import org.mmtk.vm.VM;
021
022 import org.vmmagic.pragma.*;
023 import org.vmmagic.unboxed.*;
024
025 /**
026 * This class implements <i>per-mutator thread</i> behavior
027 * and state for the <i>StickyImmix</i> plan, which implements a
028 * generational mark-sweep collector.<p>
029 *
030 * Specifically, this class defines <i>MS</i> mutator-time allocation
031 * and per-mutator thread collection semantics (flushing and restoring
032 * per-mutator allocator state).<p>
033 * *
034 * @see StickyImmix
035 * @see StickyImmixCollector
036 * @see MutatorContext
037 * @see Phase
038 */
039 @Uninterruptible
040 public class StickyImmixMutator extends ImmixMutator {
041
042 /****************************************************************************
043 * Instance fields
044 */
045
046 /**
047 *
048 */
049 private ObjectReferenceDeque modBuffer;
050
051 /****************************************************************************
052 *
053 * Initialization
054 */
055
056 /**
057 * Constructor
058 */
059 public StickyImmixMutator() {
060 super();
061 modBuffer = new ObjectReferenceDeque("mod buf", global().modPool);
062 }
063
064 /****************************************************************************
065 *
066 * Barriers
067 */
068
069 /**
070 * {@inheritDoc}<p>
071 *
072 * In this case, we remember the address of the source of the
073 * pointer if the new reference points into the nursery from
074 * non-nursery space.
075 */
076 @Override
077 @Inline
078 public final void objectReferenceWrite(ObjectReference src, Address slot,
079 ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) {
080 if (HeaderByte.isUnlogged(src))
081 logSource(src);
082 VM.barriers.objectReferenceWrite(src, tgt, metaDataA, metaDataB, mode);
083 }
084
085 /**
086 * {@inheritDoc}<p>
087 *
088 * In this case, we remember the mutated source address range and
089 * will scan that address range at GC time.
090 *
091 * @param src The source of the values to copied
092 * @param srcOffset The offset of the first source address, in
093 * bytes, relative to <code>src</code> (in principle, this could be
094 * negative).
095 * @param dst The mutated object, i.e. the destination of the copy.
096 * @param dstOffset The offset of the first destination address, in
097 * bytes relative to <code>tgt</code> (in principle, this could be
098 * negative).
099 * @param bytes The size of the region being copied, in bytes.
100 * @return True if the update was performed by the barrier, false if
101 * left to the caller (always false in this case).
102 */
103 @Override
104 @Inline
105 public final boolean objectReferenceBulkCopy(ObjectReference src, Offset srcOffset,
106 ObjectReference dst, Offset dstOffset, int bytes) {
107 if (HeaderByte.isUnlogged(src))
108 logSource(src);
109 return false;
110 }
111
112 @Override
113 @Inline
114 public boolean objectReferenceTryCompareAndSwap(ObjectReference src, Address slot,
115 ObjectReference old, ObjectReference tgt, Word metaDataA,
116 Word metaDataB, int mode) {
117 if (HeaderByte.isUnlogged(src))
118 logSource(src);
119 return VM.barriers.objectReferenceTryCompareAndSwap(src,old,tgt,metaDataA,metaDataB,mode);
120 }
121
122 /**
123 * Add an object to the modified objects buffer and mark the
124 * object has having been logged. Since duplicate entries do
125 * not raise any correctness issues, we do <i>not</i> worry
126 * about synchronization and allow threads to race to log the
127 * object, potentially including it twice (unlike reference
128 * counting where duplicates would lead to incorrect reference
129 * counts).
130 *
131 * @param src The object to be logged
132 */
133 private void logSource(ObjectReference src) {
134 HeaderByte.markAsLogged(src);
135 modBuffer.push(src);
136 }
137
138 @Override
139 public final void flushRememberedSets() {
140 modBuffer.flushLocal();
141 assertRemsetFlushed();
142 }
143
144 public final void assertRemsetFlushed() {
145 if (VM.VERIFY_ASSERTIONS) {
146 VM.assertions._assert(modBuffer.isFlushed());
147 }
148 }
149
150
151 /****************************************************************************
152 *
153 * Collection
154 */
155
156 /**
157 * {@inheritDoc}
158 */
159 @Override
160 @Inline
161 public final void collectionPhase(short phaseId, boolean primary) {
162 if (phaseId == StickyImmix.PREPARE) {
163 flushRememberedSets();
164 }
165 if (phaseId == StickyImmix.RELEASE) {
166 assertRemsetFlushed();
167 }
168
169 if (!global().collectWholeHeap) {
170 if (phaseId == StickyImmix.PREPARE) {
171 immix.prepare();
172 return;
173 }
174
175 if (phaseId == StickyImmix.RELEASE) {
176 immix.release();
177 return;
178 }
179 }
180
181 super.collectionPhase(phaseId, primary);
182 }
183
184 /****************************************************************************
185 *
186 * Miscellaneous
187 */
188
189 /** @return The active global plan as an <code>MSGen</code> instance. */
190 @Inline
191 private static StickyImmix global() {
192 return (StickyImmix) VM.activePlan.global();
193 }
194 }