001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Common Public License (CPL);
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/cpl1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.mm.mmtk;
014
015 import org.jikesrvm.SizeConstants;
016 import org.jikesrvm.runtime.Magic;
017 import org.mmtk.vm.VM;
018
019 import org.vmmagic.unboxed.*;
020 import org.vmmagic.pragma.*;
021
022 @Uninterruptible
023 public class Barriers extends org.mmtk.vm.Barriers implements SizeConstants {
024 /**
025 * Perform the actual write of the write barrier.
026 *
027 * @param ref The object that has the reference field
028 * @param slot The slot that holds the reference
029 * @param target The value that the slot will be updated to
030 * @param metaDataA The offset from the ref
031 * @param metaDataB The index of the FieldReference
032 * @param mode The context in which the write is occuring
033 */
034 @Inline
035 public final void performWriteInBarrier(ObjectReference ref, Address slot,
036 ObjectReference target, Word metaDataA,
037 Word metaDataB, int mode) {
038 Object obj = ref.toObject();
039 Offset offset = metaDataA.toOffset();
040 int location = metaDataB.toInt();
041 Magic.setObjectAtOffset(obj, offset, target.toObject(), location);
042 }
043
044 /**
045 * Perform the actual write of the write barrier, writing the value as a raw word.
046 *
047 * @param ref The object that has the reference field
048 * @param slot The slot that holds the reference
049 * @param rawTarget The value that the slot will be updated to
050 * @param metaDataA The offset from the ref
051 * @param metaDataB The index of the FieldReference
052 * @param mode The context in which the write is occuring
053 */
054 @Inline
055 public final void performRawWriteInBarrier(ObjectReference ref, Address slot,
056 Word rawTarget, Word metaDataA,
057 Word metaDataB, int mode) {
058 Object obj = ref.toObject();
059 Offset offset = metaDataA.toOffset();
060 int location = metaDataB.toInt();
061 Magic.setWordAtOffset(obj, offset, rawTarget, location);
062 }
063
064 /**
065 * Perform the actual read of the read barrier.
066 *
067 * @param ref The object that has the reference field
068 * @param slot The slot that holds the reference
069 * @param metaDataA The offset from the ref
070 * @param metaDataB The index of the FieldReference
071 * @param mode The context in which the write is occuring
072 * @return the read value
073 */
074 @Inline
075 public final ObjectReference performReadInBarrier(ObjectReference ref, Address slot,
076 Word metaDataA, Word metaDataB, int mode) {
077 Object obj = ref.toObject();
078 Offset offset = metaDataA.toOffset();
079 int location = metaDataB.toInt();
080 return ObjectReference.fromObject(Magic.getObjectAtOffset(obj, offset, location));
081 }
082
083 /**
084 * Perform the actual read of the read barrier, returning the value as a raw word.
085 *
086 * @param ref The object that has the reference field
087 * @param slot The slot that holds the reference
088 * @param metaDataA The offset from the ref
089 * @param metaDataB The index of the FieldReference
090 * @param mode The context in which the write is occuring
091 * @return the read value
092 */
093 @Inline
094 public final Word performRawReadInBarrier(ObjectReference ref, Address slot,
095 Word metaDataA, Word metaDataB, int mode) {
096 Object obj = ref.toObject();
097 Offset offset = metaDataA.toOffset();
098 int location = metaDataB.toInt();
099 return Magic.getWordAtOffset(obj, offset, location);
100 }
101
102 /**
103 * Atomically write a reference field of an object or array and return
104 * the old value of the reference field.
105 *
106 * @param ref The object that has the reference field
107 * @param slot The slot that holds the reference
108 * @param target The value that the slot will be updated to
109 * @param metaDataA The offset from the ref
110 * @param metaDataB Unused
111 * @param mode The context in which the write is occuring
112 * @return The value that was replaced by the write.
113 */
114 @Inline
115 public final ObjectReference performWriteInBarrierAtomic(
116 ObjectReference ref, Address slot,
117 ObjectReference target, Word metaDataA,
118 Word metaDataB, int mode) {
119 Object obj = ref.toObject();
120 Object newObject = target.toObject();
121 Offset offset = metaDataA.toOffset();
122 Object oldObject;
123 do {
124 oldObject = Magic.prepareObject(obj, offset);
125 } while (!Magic.attemptObject(obj, offset, oldObject, newObject));
126 return ObjectReference.fromObject(oldObject);
127 }
128
129
130 /**
131 * Atomically write a raw reference field of an object or array and return
132 * the old value of the reference field.
133 *
134 * @param ref The object that has the reference field
135 * @param slot The slot that holds the reference
136 * @param rawTarget The value that the slot will be updated to
137 * @param metaDataA The offset from the ref
138 * @param metaDataB Unused
139 * @param mode The context in which the write is occuring
140 * @return The value that was replaced by the write.
141 */
142 @Inline
143 public final Word performRawWriteInBarrierAtomic(
144 ObjectReference ref, Address slot,
145 Word rawTarget, Word metaDataA,
146 Word metaDataB, int mode) {
147 Object obj = ref.toObject();
148 Offset offset = metaDataA.toOffset();
149 Word oldValue;
150 do {
151 oldValue = Magic.prepareWord(obj, offset);
152 } while (!Magic.attemptWord(obj, offset, oldValue, rawTarget));
153 return oldValue;
154 }
155
156 /**
157 * Attempt an atomic compare and exchange in a write barrier sequence.
158 *
159 * @param ref The object that has the reference field
160 * @param slot The slot that holds the reference
161 * @param old The old reference to be swapped out
162 * @param target The value that the slot will be updated to
163 * @param metaDataA The offset from the ref
164 * @param metaDataB Unused
165 * @param mode The context in which the write is occuring
166 * @return True if the compare and swap was successful
167 */
168 @Inline
169 public final boolean tryCompareAndSwapWriteInBarrier(ObjectReference ref, Address slot,
170 ObjectReference old, ObjectReference target,
171 Word metaDataA, Word metaDataB, int mode) {
172 Object oldValue;
173 Offset offset = metaDataA.toOffset();
174 do {
175 oldValue = Magic.prepareObject(ref, offset);
176 if (oldValue != old) return false;
177 } while (!Magic.attemptObject(ref, offset, oldValue, target));
178 return true;
179 }
180
181
182 /**
183 * Attempt an atomic compare and exchange in a write barrier sequence.
184 *
185 * @param ref The object that has the reference field
186 * @param slot The slot that holds the reference
187 * @param rawOld The old reference to be swapped out
188 * @param rawTarget The value that the slot will be updated to
189 * @param metaDataA The offset from the ref
190 * @param metaDataB Unused
191 * @param mode The context in which the write is occuring
192 * @return True if the compare and swap was successful
193 */
194 @Inline
195 public final boolean tryRawCompareAndSwapWriteInBarrier(ObjectReference ref, Address slot,
196 Word rawOld, Word rawTarget, Word metaDataA,
197 Word metaDataB, int mode) {
198 Offset offset = metaDataA.toOffset();
199 do {
200 Word currentValue = Magic.prepareWord(ref, offset);
201 if (currentValue != rawOld) return false;
202 } while (!Magic.attemptObject(ref, offset, rawOld, rawTarget));
203 return true;
204 }
205
206 /**
207 * Sets an element of an object array without invoking any write
208 * barrier. This method is called by the Map class to ensure
209 * potentially-allocation-triggering write barriers do not occur in
210 * allocation slow path code.
211 *
212 * @param dst the destination array
213 * @param index the index of the element to set
214 * @param value the new value for the element
215 */
216 @UninterruptibleNoWarn
217 public final void setArrayNoBarrier(Object [] dst, int index, Object value) {
218 if (org.jikesrvm.VM.runningVM) {
219 Address base = ObjectReference.fromObject(dst).toAddress();
220 Address slot = base.plus(Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS));
221 VM.activePlan.global().storeObjectReference(slot, ObjectReference.fromObject(value));
222 } else {
223 dst[index] = value;
224 }
225 }
226 }