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 }