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    }