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.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 a boolean write barrier.
026       *
027       * @param objref The object that has the boolean field
028       * @param value The value that the slot will be updated to
029       * @param offset The offset from the ref
030       * @param location The FieldReference index to assist the store
031       * @param mode The context in which the write is occurring
032       */
033      @Inline
034      @Override
035      public final void booleanWrite(ObjectReference objref, boolean value, Word offset, Word location, int mode) {
036        Magic.setBooleanAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
037      }
038    
039      /**
040       * Perform the actual read of a boolean read barrier.
041       *
042       * @param objref The object that has the boolean field
043       * @param offset The offset from the ref
044       * @param unused Unused
045       * @param mode The context in which the write is occurring
046       * @return the read value
047       */
048      @Inline
049      @Override
050      public final boolean booleanRead(ObjectReference objref, Word offset, Word location, int mode) {
051        return Magic.getByteAtOffset(objref.toObject(), offset.toOffset()) == 0;
052      }
053    
054      /**
055       * Perform the actual write of a byte write barrier.
056       *
057       * @param objref The object that has the byte field
058       * @param value The value that the slot will be updated to
059       * @param offset The offset from the ref
060       * @param location The FieldReference index to assist the store
061       * @param mode The context in which the write is occurring
062       */
063      @Inline
064      @Override
065      public final void byteWrite(ObjectReference objref, byte value, Word offset, Word location, int mode) {
066        Magic.setByteAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
067      }
068    
069      /**
070       * Perform the actual read of a byte read barrier.
071       *
072       * @param objref The object that has the byte field
073       * @param offset The offset from the ref
074       * @param unused Unused
075       * @param mode The context in which the write is occurring
076       * @return the read value
077       */
078      @Inline
079      @Override
080      public final byte byteRead(ObjectReference objref, Word offset, Word location, int mode) {
081        return Magic.getByteAtOffset(objref.toObject(), offset.toOffset());
082      }
083    
084      /**
085       * Perform the actual write of a char write barrier.
086       *
087       * @param objref The object that has the char field
088       * @param value The value that the slot will be updated to
089       * @param offset The offset from the ref
090       * @param location The FieldReference index to assist the store
091       * @param mode The context in which the write is occurring
092       */
093      @Inline
094      @Override
095      public final void charWrite(ObjectReference objref, char value, Word offset, Word location, int mode) {
096        Magic.setCharAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
097      }
098    
099      /**
100       * Perform the actual read of a char read barrier.
101       *
102       * @param objref The object that has the char field
103       * @param offset The offset from the ref
104       * @param unused Unused
105       * @param mode The context in which the write is occurring
106       * @return the read value
107       */
108      @Inline
109      @Override
110      public final char charRead(ObjectReference objref, Word offset, Word location, int mode) {
111        return Magic.getCharAtOffset(objref.toObject(), offset.toOffset());
112      }
113    
114      /**
115       * Perform the actual write of a short write barrier.
116       *
117       * @param objref The object that has the short field
118       * @param value The value that the slot will be updated to
119       * @param offset The offset from the ref
120       * @param location The FieldReference index to assist the store
121       * @param mode The context in which the write is occurring
122       */
123      @Inline
124      @Override
125      public final void shortWrite(ObjectReference objref, short value, Word offset, Word location, int mode) {
126        Magic.setShortAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
127      }
128    
129      /**
130       * Perform the actual read of a short read barrier.
131       *
132       * @param objref The object that has the short field
133       * @param offset The offset from the ref
134       * @param unused Unused
135       * @param mode The context in which the write is occurring
136       * @return the read value
137       */
138      @Inline
139      @Override
140      public final short shortRead(ObjectReference objref, Word offset, Word location, int mode) {
141        return Magic.getShortAtOffset(objref.toObject(), offset.toOffset());
142      }
143    
144      /**
145       * Perform the actual write of a int write barrier.
146       *
147       * @param objref The object that has the int field
148       * @param value The value that the slot will be updated to
149       * @param offset The offset from the ref
150       * @param location The FieldReference index to assist the store
151       * @param mode The context in which the write is occurring
152       */
153      @Inline
154      @Override
155      public final void intWrite(ObjectReference objref, int value, Word offset, Word location, int mode) {
156        Magic.setIntAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
157      }
158    
159      /**
160       * Perform the actual read of a int read barrier.
161       *
162       * @param objref The object that has the int field
163       * @param offset The offset from the ref
164       * @param unused Unused
165       * @param mode The context in which the write is occurring
166       * @return the read value
167       */
168      @Inline
169      @Override
170      public final int intRead(ObjectReference objref, Word offset, Word location, int mode) {
171        return Magic.getIntAtOffset(objref.toObject(), offset.toOffset());
172      }
173    
174      /**
175       * Attempt an atomic compare and exchange in a write barrier sequence.
176       *
177       * @param objref The object that has the int field
178       * @param expected The old int to be swapped out
179       * @param newValue the new int
180       * @param offset The offset from the ref
181       * @param unused Unused
182       * @param mode The context in which the write is occurring
183       * @return True if the compare and swap was successful
184       */
185      @Override
186      public boolean intTryCompareAndSwap(ObjectReference objref, int expected, int newValue, Word offset, Word unused, int mode) {
187        int oldValue;
188        do {
189          oldValue = Magic.prepareInt(objref, offset.toOffset());
190          if (oldValue != expected) return false;
191        } while (!Magic.attemptInt(objref, offset.toOffset(), oldValue, newValue));
192        return true;
193      }
194    
195      /**
196       * Perform the actual write of a long write barrier.
197       *
198       * @param objref The object that has the long field
199       * @param value The value that the slot will be updated to
200       * @param offset The offset from the ref
201       * @param location The FieldReference index to assist the store
202       * @param mode The context in which the write is occurring
203       */
204      @Inline
205      @Override
206      public final void longWrite(ObjectReference objref, long value, Word offset, Word location, int mode) {
207        Magic.setLongAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
208      }
209    
210      /**
211       * Perform the actual read of a long read barrier.
212       *
213       * @param objref The object that has the long field
214       * @param offset The offset from the ref
215       * @param unused Unused
216       * @param mode The context in which the write is occurring
217       * @return the read value
218       */
219      @Inline
220      @Override
221      public final long longRead(ObjectReference objref, Word offset, Word location, int mode) {
222        return Magic.getLongAtOffset(objref.toObject(), offset.toOffset());
223      }
224    
225      /**
226       * Attempt an atomic compare and exchange in a write barrier sequence.
227       *
228       * @param objref The object that has the long field
229       * @param expected The old long to be swapped out
230       * @param newValue the new long
231       * @param offset The offset from the ref
232       * @param unused Unused
233       * @param mode The context in which the write is occurring
234       * @return True if the compare and swap was successful
235       */
236      @Override
237      public boolean longTryCompareAndSwap(ObjectReference objref, long expected, long newValue, Word offset, Word unused, int mode) {
238        long oldValue;
239        do {
240          oldValue = Magic.prepareLong(objref, offset.toOffset());
241          if (oldValue != expected) return false;
242        } while (!Magic.attemptLong(objref, offset.toOffset(), oldValue, newValue));
243        return true;
244      }
245    
246      /**
247       * Perform the actual write of a float write barrier.
248       *
249       * @param objref The object that has the float field
250       * @param value The value that the slot will be updated to
251       * @param offset The offset from the ref
252       * @param location The FieldReference index to assist the store
253       * @param mode The context in which the write is occurring
254       */
255      @Inline
256      @Override
257      public final void floatWrite(ObjectReference objref, float value, Word offset, Word location, int mode) {
258        Magic.setFloatAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
259      }
260    
261      /**
262       * Perform the actual read of a float read barrier.
263       *
264       * @param objref The object that has the float field
265       * @param offset The offset from the ref
266       * @param unused Unused
267       * @param mode The context in which the write is occurring
268       * @return the read value
269       */
270      @Inline
271      @Override
272      public final float floatRead(ObjectReference objref, Word offset, Word location, int mode) {
273        return Magic.getFloatAtOffset(objref.toObject(), offset.toOffset());
274      }
275    
276      /**
277       * Perform the actual write of a double write barrier.
278       *
279       * @param objref The object that has the double field
280       * @param value The value that the slot will be updated to
281       * @param offset The offset from the ref
282       * @param location The FieldReference index to assist the store
283       * @param mode The context in which the write is occurring
284       */
285      @Inline
286      @Override
287      public final void doubleWrite(ObjectReference objref, double value, Word offset, Word location, int mode) {
288        Magic.setDoubleAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
289      }
290    
291      /**
292       * Perform the actual read of a double read barrier.
293       *
294       * @param objref The object that has the double field
295       * @param offset The offset from the ref
296       * @param unused Unused
297       * @param mode The context in which the write is occurring
298       * @return the read value
299       */
300      @Inline
301      @Override
302      public final double doubleRead(ObjectReference objref, Word offset, Word location, int mode) {
303        return Magic.getDoubleAtOffset(objref.toObject(), offset.toOffset());
304      }
305    
306      /**
307       * Perform the actual write of an object reference write barrier.
308       *
309       * @param objref The object that has the reference field
310       * @param value The value that the slot will be updated to
311       * @param offset The offset from the ref
312       * @param location The index of the FieldReference
313       * @param mode The context in which the write is occurring
314       */
315      @Inline
316      @Override
317      public final void objectReferenceWrite(ObjectReference objref, ObjectReference value, Word offset, Word location, int mode) {
318        Magic.setObjectAtOffset(objref.toObject(), offset.toOffset(), value.toObject(), location.toInt());
319      }
320    
321      /**
322       * Perform the actual read of an object reference read barrier.
323       *
324       * @param objref The object that has the reference field
325       * @param offset The offset from the ref
326       * @param location The index of the FieldReference
327       * @param mode The context in which the write is occurring
328       * @return the object reference read value
329       */
330      @Inline
331      @Override
332      public final ObjectReference objectReferenceRead(ObjectReference objref, Word offset, Word location, int mode) {
333        return ObjectReference.fromObject(Magic.getObjectAtOffset(objref.toObject(), offset.toOffset(), location.toInt()));
334      }
335    
336      /**
337       * Perform the actual write of the non-heap write barrier.  This is
338       * used when the store is not to an object, but to a non-heap location
339       * such as statics or the stack.
340       * @param target The value that the slot will be updated to
341       * @param unusedA The offset from the ref
342       * @param unusedB Unused
343       * @param ref The object that has the reference field
344       */
345      @Inline
346      @Override
347      public final void objectReferenceNonHeapWrite(Address slot, ObjectReference target, Word unusedA, Word unusedB) {
348        slot.store(target);
349      }
350    
351      /**
352       * Atomically write a reference field of an object or array and return
353       * the old value of the reference field.
354       *
355       * @param objref The object that has the reference field
356       * @param target The value that the slot will be updated to
357       * @param offset The offset from the ref
358       * @param unused Unused
359       * @param mode The context in which the write is occurring
360       * @return The value that was replaced by the write.
361       */
362      @Inline
363      @Override
364      public final ObjectReference objectReferenceAtomicWrite(ObjectReference objref, ObjectReference target, Word offset, Word unused, int mode) {
365        Object obj = objref.toObject();
366        Object newObject = target.toObject();
367        Object oldObject;
368        do {
369          oldObject = Magic.prepareObject(obj, offset.toOffset());
370        } while (!Magic.attemptObject(obj, offset.toOffset(), oldObject, newObject));
371        return ObjectReference.fromObject(oldObject);
372      }
373    
374      /**
375       * Attempt an atomic compare and exchange in a write barrier sequence.
376       *
377       * @param objref The object that has the reference field
378       * @param old The old reference to be swapped out
379       * @param target The value that the slot will be updated to
380       * @param offset The offset from the ref
381       * @param unused Unused
382       * @param mode The context in which the write is occurring
383       * @return True if the compare and swap was successful
384       */
385      @Inline
386      @Override
387      public final boolean objectReferenceTryCompareAndSwap(ObjectReference objref, ObjectReference old, ObjectReference target, Word offset, Word unused, int mode) {
388        Object oldValue;
389        do {
390          oldValue = Magic.prepareObject(objref, offset.toOffset());
391          if (oldValue != old) return false;
392        } while (!Magic.attemptObject(objref, offset.toOffset(), oldValue, target));
393        return true;
394      }
395    
396      /**
397       * Perform the actual write of the write barrier, writing the value as a raw Word.
398       *
399       * @param ref The object that has the Word field
400       * @param target The value that the slot will be updated to
401       * @param offset The offset from the ref
402       * @param location The index of the FieldReference
403       * @param mode The context in which the write is occurring
404       */
405      @Inline
406      @Override
407      public final void wordWrite(ObjectReference ref, Word target,
408          Word offset, Word location, int mode) {
409        Magic.setWordAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
410      }
411    
412      /**
413       * Atomically write a raw reference field of an object or array and return
414       * the old value of the reference field.
415       *
416       * @param ref The object that has the Word field
417       * @param target The value that the slot will be updated to
418       * @param offset The offset from the ref
419       * @param unused Unused
420       * @param mode The context in which the write is occurring
421       * @return The value that was replaced by the write.
422       */
423      @Inline
424      @Override
425      public final Word wordAtomicWrite(ObjectReference ref, Word target,
426          Word offset, Word unused, int mode) {
427        Word oldValue;
428        do {
429          oldValue = Magic.prepareWord(ref.toObject(), offset.toOffset());
430        } while (!Magic.attemptWord(ref.toObject(), offset.toOffset(), oldValue, target));
431        return oldValue;
432      }
433    
434      /**
435       * Attempt an atomic compare and exchange in a write barrier sequence.
436       *
437       * @param ref The object that has the Word field
438       * @param old The old Word to be swapped out
439       * @param target The value that the slot will be updated to
440       * @param offset The offset from the ref
441       * @param unused Unused
442       * @param mode The context in which the write is occurring
443       * @return True if the compare and swap was successful
444       */
445      @Inline
446      @Override
447      public final boolean wordTryCompareAndSwap(ObjectReference ref, Word old, Word target,
448          Word offset, Word unused, int mode) {
449        do {
450          Word currentValue = Magic.prepareWord(ref, offset.toOffset());
451          if (currentValue != old) return false;
452        } while (!Magic.attemptWord(ref, offset.toOffset(), old, target));
453        return true;
454      }
455    
456      /**
457       * Perform the actual read of the read barrier, returning the value as a raw Word.
458       *
459       * @param ref The object that has the Word field
460       * @param offset The offset from the ref
461       * @param location The index of the FieldReference
462       * @param mode The context in which the write is occurring
463       * @return the read value
464       */
465      @Inline
466      @Override
467      public final Word wordRead(ObjectReference ref,
468            Word offset, Word location, int mode) {
469        return Magic.getWordAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
470      }
471    
472      /**
473       * Perform the actual write of the write barrier, writing the value as a raw Address.
474       *
475       * @param ref The object that has the Address field
476       * @param target The value that the slot will be updated to
477       * @param offset The offset from the ref
478       * @param location The index of the FieldReference
479       * @param mode The context in which the write is occurring
480       */
481      @Inline
482      @Override
483      public final void addressWrite(ObjectReference ref, Address target,
484          Word offset, Word location, int mode) {
485        Magic.setAddressAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
486      }
487    
488      /**
489       * Perform the actual read of the read barrier, returning the value as a raw Address.
490       *
491       * @param ref The object that has the Address field
492       * @param offset The offset from the ref
493       * @param location The index of the FieldReference
494       * @param mode The context in which the write is occurring
495       * @return the read value
496       */
497      @Inline
498      @Override
499      public final Address addressRead(ObjectReference ref,
500            Word offset, Word location, int mode) {
501        return Magic.getAddressAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
502      }
503    
504      /**
505       * Attempt an atomic compare and exchange in a write barrier sequence.
506       *
507       * @param objref The object that has the Address field
508       * @param expected The old Address to be swapped out
509       * @param newValue the new Address
510       * @param offset The offset from the ref
511       * @param unused Unused
512       * @param mode The context in which the write is occurring
513       * @return True if the compare and swap was successful
514       */
515      @Override
516      public boolean addressTryCompareAndSwap(ObjectReference objref, Address expected, Address newValue, Word offset, Word unused, int mode) {
517        Address oldValue;
518        do {
519          oldValue = Magic.prepareAddress(objref, offset.toOffset());
520          if (oldValue != expected) return false;
521        } while (!Magic.attemptAddress(objref, offset.toOffset(), oldValue, newValue));
522        return true;
523      }
524    
525      /**
526       * Perform the actual write of the write barrier, writing the value as a raw Offset.
527       *
528       * @param ref The object that has the Offset field
529       * @param target The value that the slot will be updated to
530       * @param offset The offset from the ref
531       * @param location The index of the FieldReference
532       * @param mode The context in which the write is occurring
533       */
534      @Inline
535      @Override
536      public final void offsetWrite(ObjectReference ref, Offset target,
537          Word offset, Word location, int mode) {
538        Magic.setOffsetAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
539      }
540    
541      /**
542       * Perform the actual read of the read barrier, returning the value as a raw Offset.
543       *
544       * @param ref The object that has the Offset field
545       * @param offset The offset from the ref
546       * @param location The index of the FieldReference
547       * @param mode The context in which the write is occurring
548       * @return the read value
549       */
550      @Inline
551      @Override
552      public final Offset offsetRead(ObjectReference ref,
553            Word offset, Word location, int mode) {
554        return Magic.getOffsetAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
555      }
556    
557      /**
558       * Perform the actual write of the write barrier, writing the value as a raw Extent.
559       *
560       * @param ref The object that has the Extent field
561       * @param target The value that the slot will be updated to
562       * @param offset The offset from the ref
563       * @param location The index of the FieldReference
564       * @param mode The context in which the write is occurring
565       */
566      @Inline
567      @Override
568      public final void extentWrite(ObjectReference ref, Extent target,
569          Word offset, Word location, int mode) {
570        Magic.setExtentAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
571      }
572    
573      /**
574       * Perform the actual read of the read barrier, returning the value as a raw Extent.
575       *
576       * @param ref The object that has the Extent field
577       * @param offset The offset from the ref
578       * @param location The index of the FieldReference
579       * @param mode The context in which the write is occurring
580       * @return the read value
581       */
582      @Inline
583      @Override
584      public final Extent extentRead(ObjectReference ref,
585            Word offset, Word location, int mode) {
586        return Magic.getExtentAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
587      }
588    
589      /**
590       * Sets an element of an object array without invoking any write
591       * barrier.  This method is called by the Map class to ensure
592       * potentially-allocation-triggering write barriers do not occur in
593       * allocation slow path code.
594       *
595       * @param dst the destination array
596       * @param index the index of the element to set
597       * @param value the new value for the element
598       */
599      @UninterruptibleNoWarn
600      @Override
601      public final void objectArrayStoreNoGCBarrier(Object[] dst, int index, Object value) {
602        if (org.jikesrvm.VM.runningVM) {
603          Address base = ObjectReference.fromObject(dst).toAddress();
604          Address slot = base.plus(Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS));
605          VM.activePlan.global().storeObjectReference(slot, ObjectReference.fromObject(value));
606        } else {
607          dst[index] = value;
608        }
609      }
610    }