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 location 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 location 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 location 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 location 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 location 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        if (org.jikesrvm.VM.BuildForIA32) {
188          return Magic.attemptInt(objref.toObject(), offset.toOffset(), expected, newValue);
189        } else {
190          int oldValue;
191          do {
192            oldValue = Magic.prepareInt(objref, offset.toOffset());
193            if (oldValue != expected) return false;
194          } while (!Magic.attemptInt(objref, offset.toOffset(), oldValue, newValue));
195          return true;
196        }
197      }
198    
199      /**
200       * Perform the actual write of a long write barrier.
201       *
202       * @param objref The object that has the long field
203       * @param value The value that the slot will be updated to
204       * @param offset The offset from the ref
205       * @param location The FieldReference index to assist the store
206       * @param mode The context in which the write is occurring
207       */
208      @Inline
209      @Override
210      public final void longWrite(ObjectReference objref, long value, Word offset, Word location, int mode) {
211        Magic.setLongAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
212      }
213    
214      /**
215       * Perform the actual read of a long read barrier.
216       *
217       * @param objref The object that has the long field
218       * @param offset The offset from the ref
219       * @param location Unused
220       * @param mode The context in which the write is occurring
221       * @return the read value
222       */
223      @Inline
224      @Override
225      public final long longRead(ObjectReference objref, Word offset, Word location, int mode) {
226        return Magic.getLongAtOffset(objref.toObject(), offset.toOffset());
227      }
228    
229      /**
230       * Attempt an atomic compare and exchange in a write barrier sequence.
231       *
232       * @param objref The object that has the long field
233       * @param expected The old long to be swapped out
234       * @param newValue the new long
235       * @param offset The offset from the ref
236       * @param unused Unused
237       * @param mode The context in which the write is occurring
238       * @return True if the compare and swap was successful
239       */
240      @Override
241      public boolean longTryCompareAndSwap(ObjectReference objref, long expected, long newValue, Word offset, Word unused, int mode) {
242        if (org.jikesrvm.VM.BuildForIA32) {
243          return Magic.attemptLong(objref.toObject(), offset.toOffset(), expected, newValue);
244        } else {
245          long oldValue;
246          do {
247            oldValue = Magic.prepareLong(objref, offset.toOffset());
248            if (oldValue != expected) return false;
249          } while (!Magic.attemptLong(objref, offset.toOffset(), oldValue, newValue));
250          return true;
251        }
252      }
253    
254      /**
255       * Perform the actual write of a float write barrier.
256       *
257       * @param objref The object that has the float field
258       * @param value The value that the slot will be updated to
259       * @param offset The offset from the ref
260       * @param location The FieldReference index to assist the store
261       * @param mode The context in which the write is occurring
262       */
263      @Inline
264      @Override
265      public final void floatWrite(ObjectReference objref, float value, Word offset, Word location, int mode) {
266        Magic.setFloatAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
267      }
268    
269      /**
270       * Perform the actual read of a float read barrier.
271       *
272       * @param objref The object that has the float field
273       * @param offset The offset from the ref
274       * @param location Unused
275       * @param mode The context in which the write is occurring
276       * @return the read value
277       */
278      @Inline
279      @Override
280      public final float floatRead(ObjectReference objref, Word offset, Word location, int mode) {
281        return Magic.getFloatAtOffset(objref.toObject(), offset.toOffset());
282      }
283    
284      /**
285       * Perform the actual write of a double write barrier.
286       *
287       * @param objref The object that has the double field
288       * @param value The value that the slot will be updated to
289       * @param offset The offset from the ref
290       * @param location The FieldReference index to assist the store
291       * @param mode The context in which the write is occurring
292       */
293      @Inline
294      @Override
295      public final void doubleWrite(ObjectReference objref, double value, Word offset, Word location, int mode) {
296        Magic.setDoubleAtOffset(objref.toObject(), offset.toOffset(), value, location.toInt());
297      }
298    
299      /**
300       * Perform the actual read of a double read barrier.
301       *
302       * @param objref The object that has the double field
303       * @param offset The offset from the ref
304       * @param location Unused
305       * @param mode The context in which the write is occurring
306       * @return the read value
307       */
308      @Inline
309      @Override
310      public final double doubleRead(ObjectReference objref, Word offset, Word location, int mode) {
311        return Magic.getDoubleAtOffset(objref.toObject(), offset.toOffset());
312      }
313    
314      /**
315       * Perform the actual write of an object reference write barrier.
316       *
317       * @param objref The object that has the reference field
318       * @param value The value that the slot will be updated to
319       * @param offset The offset from the ref
320       * @param location The index of the FieldReference
321       * @param mode The context in which the write is occurring
322       */
323      @Inline
324      @Override
325      public final void objectReferenceWrite(ObjectReference objref, ObjectReference value, Word offset, Word location, int mode) {
326        Magic.setObjectAtOffset(objref.toObject(), offset.toOffset(), value.toObject(), location.toInt());
327      }
328    
329      /**
330       * Perform the actual read of an object reference read barrier.
331       *
332       * @param objref The object that has the reference field
333       * @param offset The offset from the ref
334       * @param location The index of the FieldReference
335       * @param mode The context in which the write is occurring
336       * @return the object reference read value
337       */
338      @Inline
339      @Override
340      public final ObjectReference objectReferenceRead(ObjectReference objref, Word offset, Word location, int mode) {
341        return ObjectReference.fromObject(Magic.getObjectAtOffset(objref.toObject(), offset.toOffset(), location.toInt()));
342      }
343    
344      /**
345       * Perform the actual write of the non-heap write barrier.  This is
346       * used when the store is not to an object, but to a non-heap location
347       * such as statics or the stack.
348       * @param slot The slot to be updated
349       * @param target The value that the slot will be updated to
350       * @param unusedA Unused
351       * @param unusedB Unused
352    
353       */
354      @Inline
355      @Override
356      public final void objectReferenceNonHeapWrite(Address slot, ObjectReference target, Word unusedA, Word unusedB) {
357        slot.store(target);
358      }
359    
360      /**
361       * Atomically write a reference field of an object or array and return
362       * the old value of the reference field.
363       *
364       * @param objref The object that has the reference field
365       * @param target The value that the slot will be updated to
366       * @param offset The offset from the ref
367       * @param unused Unused
368       * @param mode The context in which the write is occurring
369       * @return The value that was replaced by the write.
370       */
371      @Inline
372      @Override
373      public final ObjectReference objectReferenceAtomicWrite(ObjectReference objref, ObjectReference target, Word offset, Word unused, int mode) {
374        Object obj = objref.toObject();
375        Object newObject = target.toObject();
376        Object oldObject;
377        do {
378          oldObject = Magic.prepareObject(obj, offset.toOffset());
379        } while (!Magic.attemptObject(obj, offset.toOffset(), oldObject, newObject));
380        return ObjectReference.fromObject(oldObject);
381      }
382    
383      /**
384       * Attempt an atomic compare and exchange in a write barrier sequence.
385       *
386       * @param objref The object that has the reference field
387       * @param old The old reference to be swapped out
388       * @param target The value that the slot will be updated to
389       * @param offset The offset from the ref
390       * @param unused Unused
391       * @param mode The context in which the write is occurring
392       * @return True if the compare and swap was successful
393       */
394      @Inline
395      @Override
396      public final boolean objectReferenceTryCompareAndSwap(ObjectReference objref, ObjectReference old, ObjectReference target, Word offset, Word unused, int mode) {
397        if (org.jikesrvm.VM.BuildForIA32) {
398          return Magic.attemptObject(objref.toObject(), offset.toOffset(), old.toObject(), target.toObject());
399        } else {
400          Object oldValue;
401          do {
402            oldValue = Magic.prepareObject(objref, offset.toOffset());
403            if (oldValue != old) return false;
404          } while (!Magic.attemptObject(objref, offset.toOffset(), oldValue, target));
405          return true;
406        }
407      }
408    
409      /**
410       * Perform the actual write of the write barrier, writing the value as a raw Word.
411       *
412       * @param ref The object that has the Word field
413       * @param target The value that the slot will be updated to
414       * @param offset The offset from the ref
415       * @param location The index of the FieldReference
416       * @param mode The context in which the write is occurring
417       */
418      @Inline
419      @Override
420      public final void wordWrite(ObjectReference ref, Word target,
421          Word offset, Word location, int mode) {
422        Magic.setWordAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
423      }
424    
425      /**
426       * Atomically write a raw reference field of an object or array and return
427       * the old value of the reference field.
428       *
429       * @param ref The object that has the Word field
430       * @param target The value that the slot will be updated to
431       * @param offset The offset from the ref
432       * @param unused Unused
433       * @param mode The context in which the write is occurring
434       * @return The value that was replaced by the write.
435       */
436      @Inline
437      @Override
438      public final Word wordAtomicWrite(ObjectReference ref, Word target,
439          Word offset, Word unused, int mode) {
440        Word oldValue;
441        do {
442          oldValue = Magic.prepareWord(ref.toObject(), offset.toOffset());
443        } while (!Magic.attemptWord(ref.toObject(), offset.toOffset(), oldValue, target));
444        return oldValue;
445      }
446    
447      /**
448       * Attempt an atomic compare and exchange in a write barrier sequence.
449       *
450       * @param ref The object that has the Word field
451       * @param old The old Word to be swapped out
452       * @param target The value that the slot will be updated to
453       * @param offset The offset from the ref
454       * @param unused Unused
455       * @param mode The context in which the write is occurring
456       * @return True if the compare and swap was successful
457       */
458      @Inline
459      @Override
460      public final boolean wordTryCompareAndSwap(ObjectReference ref, Word old, Word target, Word offset, Word unused, int mode) {
461        if (org.jikesrvm.VM.BuildForIA32) {
462          return Magic.attemptWord(ref.toObject(), offset.toOffset(), old, target);
463        } else {
464          do {
465            Word currentValue = Magic.prepareWord(ref, offset.toOffset());
466            if (currentValue != old) return false;
467          } while (!Magic.attemptWord(ref, offset.toOffset(), old, target));
468          return true;
469        }
470      }
471    
472      /**
473       * Perform the actual read of the read barrier, returning the value as a raw Word.
474       *
475       * @param ref The object that has the Word field
476       * @param offset The offset from the ref
477       * @param location The index of the FieldReference
478       * @param mode The context in which the write is occurring
479       * @return the read value
480       */
481      @Inline
482      @Override
483      public final Word wordRead(ObjectReference ref,
484            Word offset, Word location, int mode) {
485        return Magic.getWordAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
486      }
487    
488      /**
489       * Perform the actual write of the write barrier, writing the value as a raw Address.
490       *
491       * @param ref The object that has the Address field
492       * @param target The value that the slot will be updated to
493       * @param offset The offset from the ref
494       * @param location The index of the FieldReference
495       * @param mode The context in which the write is occurring
496       */
497      @Inline
498      @Override
499      public final void addressWrite(ObjectReference ref, Address target,
500          Word offset, Word location, int mode) {
501        Magic.setAddressAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
502      }
503    
504      /**
505       * Perform the actual read of the read barrier, returning the value as a raw Address.
506       *
507       * @param ref The object that has the Address field
508       * @param offset The offset from the ref
509       * @param location The index of the FieldReference
510       * @param mode The context in which the write is occurring
511       * @return the read value
512       */
513      @Inline
514      @Override
515      public final Address addressRead(ObjectReference ref,
516            Word offset, Word location, int mode) {
517        return Magic.getAddressAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
518      }
519    
520      /**
521       * Attempt an atomic compare and exchange in a write barrier sequence.
522       *
523       * @param objref The object that has the Address field
524       * @param expected The old Address to be swapped out
525       * @param newValue the new Address
526       * @param offset The offset from the ref
527       * @param unused Unused
528       * @param mode The context in which the write is occurring
529       * @return True if the compare and swap was successful
530       */
531      @Override
532      public boolean addressTryCompareAndSwap(ObjectReference objref, Address expected, Address newValue, Word offset, Word unused, int mode) {
533        if (org.jikesrvm.VM.BuildForIA32) {
534          return Magic.attemptAddress(objref.toObject(), offset.toOffset(), expected, newValue);
535        } else {
536          Address oldValue;
537          do {
538            oldValue = Magic.prepareAddress(objref, offset.toOffset());
539            if (oldValue != expected) return false;
540          } while (!Magic.attemptAddress(objref, offset.toOffset(), oldValue, newValue));
541          return true;
542        }
543      }
544    
545      /**
546       * Perform the actual write of the write barrier, writing the value as a raw Offset.
547       *
548       * @param ref The object that has the Offset field
549       * @param target The value that the slot will be updated to
550       * @param offset The offset from the ref
551       * @param location The index of the FieldReference
552       * @param mode The context in which the write is occurring
553       */
554      @Inline
555      @Override
556      public final void offsetWrite(ObjectReference ref, Offset target,
557          Word offset, Word location, int mode) {
558        Magic.setOffsetAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
559      }
560    
561      /**
562       * Perform the actual read of the read barrier, returning the value as a raw Offset.
563       *
564       * @param ref The object that has the Offset field
565       * @param offset The offset from the ref
566       * @param location The index of the FieldReference
567       * @param mode The context in which the write is occurring
568       * @return the read value
569       */
570      @Inline
571      @Override
572      public final Offset offsetRead(ObjectReference ref,
573            Word offset, Word location, int mode) {
574        return Magic.getOffsetAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
575      }
576    
577      /**
578       * Perform the actual write of the write barrier, writing the value as a raw Extent.
579       *
580       * @param ref The object that has the Extent field
581       * @param target The value that the slot will be updated to
582       * @param offset The offset from the ref
583       * @param location The index of the FieldReference
584       * @param mode The context in which the write is occurring
585       */
586      @Inline
587      @Override
588      public final void extentWrite(ObjectReference ref, Extent target,
589          Word offset, Word location, int mode) {
590        Magic.setExtentAtOffset(ref.toObject(), offset.toOffset(), target, location.toInt());
591      }
592    
593      /**
594       * Perform the actual read of the read barrier, returning the value as a raw Extent.
595       *
596       * @param ref The object that has the Extent field
597       * @param offset The offset from the ref
598       * @param location The index of the FieldReference
599       * @param mode The context in which the write is occurring
600       * @return the read value
601       */
602      @Inline
603      @Override
604      public final Extent extentRead(ObjectReference ref,
605            Word offset, Word location, int mode) {
606        return Magic.getExtentAtOffset(ref.toObject(), offset.toOffset(), location.toInt());
607      }
608    
609      /**
610       * Sets an element of an object array without invoking any write
611       * barrier.  This method is called by the Map class to ensure
612       * potentially-allocation-triggering write barriers do not occur in
613       * allocation slow path code.
614       *
615       * @param dst the destination array
616       * @param index the index of the element to set
617       * @param value the new value for the element
618       */
619      @UninterruptibleNoWarn
620      @Override
621      public final void objectArrayStoreNoGCBarrier(Object[] dst, int index, Object value) {
622        if (org.jikesrvm.VM.runningVM) {
623          Address base = ObjectReference.fromObject(dst).toAddress();
624          Address slot = base.plus(Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS));
625          VM.activePlan.global().storeObjectReference(slot, ObjectReference.fromObject(value));
626        } else {
627          dst[index] = value;
628        }
629      }
630    }