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