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.objectmodel; 014 015import static org.jikesrvm.objectmodel.JavaHeaderConstants.ADDRESS_BASED_HASHING; 016import static org.jikesrvm.objectmodel.JavaHeaderConstants.ARRAY_LENGTH_OFFSET; 017import static org.jikesrvm.objectmodel.JavaHeaderConstants.HASHCODE_BYTES; 018import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_INT; 019 020import org.jikesrvm.VM; 021import org.jikesrvm.classloader.RVMArray; 022import org.jikesrvm.classloader.RVMClass; 023import org.jikesrvm.classloader.RVMType; 024import org.jikesrvm.mm.mminterface.AlignmentEncoding; 025import org.jikesrvm.mm.mminterface.MemoryManager; 026import org.jikesrvm.runtime.Magic; 027import org.jikesrvm.scheduler.Lock; 028import org.jikesrvm.scheduler.RVMThread; 029import org.vmmagic.pragma.Entrypoint; 030import org.vmmagic.pragma.Inline; 031import org.vmmagic.pragma.Interruptible; 032import org.vmmagic.pragma.Uninterruptible; 033import org.vmmagic.pragma.Unpreemptible; 034import org.vmmagic.unboxed.Address; 035import org.vmmagic.unboxed.Extent; 036import org.vmmagic.unboxed.ObjectReference; 037import org.vmmagic.unboxed.Offset; 038import org.vmmagic.unboxed.Word; 039 040/** 041 * The interface to the object model definition accessible to the 042 * virtual machine. <p> 043 * 044 * Conceptually each Java object is composed of the following pieces: 045 * <ul> 046 * <li> The JavaHeader defined by {@link JavaHeader}. This portion of the 047 * object supports language-level functions such as locking, hashcodes, 048 * dynamic type checking, virtual function invocation, and array length. 049 * <li> The GCHeader defined by {@link MemoryManager}. This portion 050 * of the object supports allocator-specific requirements such as 051 * mark/barrier bits, reference counts, etc. 052 * <li> The MiscHeader defined by {@link MiscHeader}. This portion supports 053 * various other clients that want to add bits/words to all objects. 054 * Typical uses are profiling and instrumentation (basically this is a 055 * way to add an instance field to java.lang.Object). 056 * <li> The instance fields. Currently defined by various classloader classes. 057 * Factoring this code out and making it possible to lay out the instance 058 * fields in different ways is a todo item. 059 * </ul> 060 * 061 * Every object's header contains the three portions outlined above. 062 * 063 * <pre> 064 * |<- lo memory hi memory ->| 065 * 066 * SCALAR LAYOUT: 067 * |<---------- scalar header --------->| 068 * +----------+------------+------------+------+------+------+--------+ 069 * | GCHeader | MiscHeader | JavaHeader | fldO | fld1 | fldx | fldN-1 | 070 * +----------+------------+------------+------+------+------+--------+ 071 * ^ JHOFF ^objref 072 * . 073 * ARRAY LAYOUT: . 074 * |<---------- array header ----------------->| 075 * +----------+------------+------------+------+------+------+------+------+ 076 * | GCHeader | MiscHeader | JavaHeader | len | elt0 | elt1 | ... |eltN-1| 077 * +----------+------------+------------+------+------+------+------+------+ 078 * ^ JHOFF ^objref 079 * </pre> 080 * <p> 081 * Assumptions: 082 * <ul> 083 * <li> Each portion of the header (JavaHeader, GCHeader, MiscHeader) 084 * is some multiple of 4 bytes (possibly 0). This simplifies access, since we 085 * can access each portion independently without having to worry about word tearing. 086 * <li> The JavaHeader exports k (>=0) unused contiguous bits that can be used 087 * by the GCHeader and MiscHeader. The GCHeader gets first dibs on these bits. 088 * The GCHeader should use bits 0..i, MiscHeader should use bits i..k. 089 * <li> JHOFF is a constant for a given configuration. 090 * </ul> 091 * 092 * This model allows efficient array access: the array pointer can be 093 * used directly in the base+offset subscript calculation, with no 094 * additional constant required.<p> 095 * 096 * This model allows free null pointer checking for most reads: a 097 * small offset from that reference will wrap around to either very 098 * high or very low unmapped memory in the case of a null pointer. As 099 * long as these segments of memory are not mapped to the current 100 * process, loads/stores through such a pointer will cause a trap that 101 * we can catch with a unix signal handler.<p> 102 * 103 * Note the key invariant that all elements of the header are 104 * available at the same offset from an objref for both arrays and 105 * scalar objects.<p> 106 * 107 * Note that this model allows for arbitrary growth of the GC header 108 * to the left of the object. A possible TODO item is to modify the 109 * necessary interfaces within this class and JavaHeader to allow 110 * moveObject, bytesUsed, bytesRequiredWhenCopied, etc. to tell this 111 * class how many GC header bytes have been allocated. As these calls 112 * would be constant within the constant of the call the optimising 113 * compiler should be able to allow this at minimal cost.<p> 114 * 115 * Another possible TODO item is to include support for linear 116 * scanning, where it is possible to move from one object to the next 117 * under contiguous allocation. At the moment this is in conflict with 118 * object alignment code for objects with long/double fields. We could 119 * possibly include the code anyway but require that the alignment 120 * code is switched off, or that all objects are aligned. Linear 121 * scanning is used in several GC algorithms including card-marking 122 * and compaction. 123 * 124 * @see JavaHeader 125 * @see MiscHeader 126 * @see MemoryManager 127 */ 128@Uninterruptible 129public class ObjectModel { 130 131 /** Should we gather stats on hash code state transitions for address-based hashing? */ 132 public static final boolean HASH_STATS = false; 133 /** count number of Object.hashCode() operations */ 134 public static int hashRequests = 0; 135 /** count transitions from UNHASHED to HASHED */ 136 public static int hashTransition1 = 0; 137 /** count transitions from HASHED to HASHED_AND_MOVED */ 138 public static int hashTransition2 = 0; 139 140 /** Whether to pack bytes and shorts into 32bit fields*/ 141 private static final boolean PACKED = true; 142 143 /** Layout widget */ 144 private static final FieldLayout layout; 145 146 static { 147 if (PACKED) { 148 layout = new FieldLayoutPacked(true, true); 149 } else { 150 layout = new FieldLayoutUnpacked(true, true); 151 } 152 } 153 154 /** 155 * Layout the instance fields declared in this class. 156 * @param klass the class to layout 157 */ 158 @Interruptible 159 public static void layoutInstanceFields(RVMClass klass) { 160 layout.layoutInstanceFields(klass); 161 } 162 163 /** 164 * Given a reference, return an address which is guaranteed to be inside 165 * the memory region allocated to the object. 166 * 167 * @param ref an object 168 * @return an address that's inside the memory region allocated to the 169 * object 170 */ 171 public static Address getPointerInMemoryRegion(ObjectReference ref) { 172 return JavaHeader.getPointerInMemoryRegion(ref); 173 } 174 175 /** 176 * @return the offset of the array length field from an object reference 177 * (in bytes) 178 */ 179 public static Offset getArrayLengthOffset() { 180 return ARRAY_LENGTH_OFFSET; 181 } 182 183 public static TIB getTIB(ObjectReference ptr) { 184 return getTIB(ptr.toObject()); 185 } 186 187 public static TIB getTIB(Object o) { 188 return JavaHeader.getTIB(o); 189 } 190 191 public static void setTIB(ObjectReference ptr, TIB tib) { 192 setTIB(ptr.toObject(), tib); 193 } 194 195 public static void setTIB(Object ref, TIB tib) { 196 JavaHeader.setTIB(ref, tib); 197 } 198 199 /** 200 * Sets the TIB for an object during bootimage writing. 201 * 202 * @param bootImage the bootimage 203 * @param refAddress the object's address 204 * @param tibAddr the TIB's address 205 * @param type the object's type 206 */ 207 @Interruptible 208 public static void setTIB(BootImageInterface bootImage, Address refAddress, Address tibAddr, RVMType type) { 209 JavaHeader.setTIB(bootImage, refAddress, tibAddr, type); 210 } 211 212 /** 213 * Get the pointer just past an object. 214 * 215 * @param obj the object in question 216 * @return first word after the object 217 */ 218 public static Address getObjectEndAddress(Object obj) { 219 TIB tib = getTIB(obj); 220 RVMType type = tib.getType(); 221 if (type.isClassType()) { 222 return getObjectEndAddress(obj, type.asClass()); 223 } else { 224 int numElements = Magic.getArrayLength(obj); 225 return getObjectEndAddress(obj, type.asArray(), numElements); 226 } 227 } 228 229 /** 230 * Gets the pointer just past an object. 231 * 232 * @param object the object in question 233 * @param type the object's class 234 * @return first word after the scalar object 235 */ 236 public static Address getObjectEndAddress(Object object, RVMClass type) { 237 return JavaHeader.getObjectEndAddress(object, type); 238 } 239 240 /** 241 * Gets the pointer just past an object. 242 * 243 * @param object the object in question 244 * @param type the object's class 245 * @param elements the array's length 246 * @return the first word after the array 247 */ 248 public static Address getObjectEndAddress(Object object, RVMArray type, int elements) { 249 return JavaHeader.getObjectEndAddress(object, type, elements); 250 } 251 252 /** 253 * Get an object reference from the address the lowest word of the object was allocated. 254 * 255 * @param start the lowest word in the storage of an allocated object 256 * @return the object reference for the object 257 */ 258 public static ObjectReference getObjectFromStartAddress(Address start) { 259 return JavaHeader.getObjectFromStartAddress(start); 260 } 261 262 /** 263 * Gets an object reference from the address the lowest word of the object was allocated. 264 * 265 * @param start the lowest word in the storage of an allocated object 266 * @return the object reference for the object 267 */ 268 public static ObjectReference getScalarFromStartAddress(Address start) { 269 return JavaHeader.getScalarFromStartAddress(start); 270 } 271 272 /** 273 * Gets an object reference from the address the lowest word of the object was allocated. 274 * 275 * @param start the lowest word in the storage of an allocated object 276 * @return the object reference for the object 277 */ 278 public static ObjectReference getArrayFromStartAddress(Address start) { 279 return JavaHeader.getArrayFromStartAddress(start); 280 } 281 282 /** 283 * @param obj an object 284 * @return the next object in the heap under contiguous allocation 285 */ 286 public static ObjectReference getNextObject(ObjectReference obj) { 287 TIB tib = getTIB(obj); 288 RVMType type = tib.getType(); 289 if (type.isClassType()) { 290 return getNextObject(obj, type.asClass()); 291 } else { 292 int numElements = Magic.getArrayLength(obj); 293 return getNextObject(obj, type.asArray(), numElements); 294 } 295 } 296 297 /** 298 * Gets the next object after this scalar under contiguous allocation. 299 * 300 * @param obj the current object, which must be a scalar 301 * @param type the object's type 302 * @return the next scalar object in the heap 303 */ 304 public static ObjectReference getNextObject(ObjectReference obj, RVMClass type) { 305 return JavaHeader.getNextObject(obj, type); 306 } 307 308 /** 309 * Get the next object after this array under contiguous allocation. 310 * 311 * @param obj the current object, which must be an array 312 * @param type the object's type 313 * @param numElements the length of the array 314 * @return the next scalar object in the heap 315 */ 316 public static ObjectReference getNextObject(ObjectReference obj, RVMArray type, int numElements) { 317 return JavaHeader.getNextObject(obj, type, numElements); 318 } 319 320 /** 321 * Gets the reference of an object after copying to a specified region. 322 * 323 * @param obj the object to copy 324 * @param to the target address for the copy 325 * @return the reference of the copy 326 */ 327 public static Object getReferenceWhenCopiedTo(Object obj, Address to) { 328 TIB tib = getTIB(obj); 329 RVMType type = tib.getType(); 330 if (type.isClassType()) { 331 return getReferenceWhenCopiedTo(obj, to, type.asClass()); 332 } else { 333 return getReferenceWhenCopiedTo(obj, to, type.asArray()); 334 } 335 } 336 337 /** 338 * @param obj an object 339 * @return the number of bytes used by the object 340 */ 341 public static int bytesUsed(Object obj) { 342 TIB tib = getTIB(obj); 343 RVMType type = tib.getType(); 344 if (type.isClassType()) { 345 return bytesUsed(obj, type.asClass()); 346 } else { 347 int numElements = Magic.getArrayLength(obj); 348 return bytesUsed(obj, type.asArray(), numElements); 349 } 350 } 351 352 /** 353 * how many bytes are used by the scalar? 354 * 355 * @param obj an object 356 * @param type the object's type 357 * @return the number of bytes used by the object 358 */ 359 public static int bytesUsed(Object obj, RVMClass type) { 360 return JavaHeader.bytesUsed(obj, type); 361 } 362 363 /** 364 * how many bytes are used by the array? 365 * 366 * @param obj an object 367 * @param type the object's type 368 * @param numElements the array's length 369 * @return the number of bytes used by the object 370 */ 371 public static int bytesUsed(Object obj, RVMArray type, int numElements) { 372 return JavaHeader.bytesUsed(obj, type, numElements); 373 } 374 375 /** 376 * @param obj the object 377 * @return number of bytes that are required when the object is copied by GC 378 */ 379 public static int bytesRequiredWhenCopied(Object obj) { 380 TIB tib = getTIB(obj); 381 RVMType type = tib.getType(); 382 if (type.isClassType()) { 383 return bytesRequiredWhenCopied(obj, type.asClass()); 384 } else { 385 int numElements = Magic.getArrayLength(obj); 386 return bytesRequiredWhenCopied(obj, type.asArray(), numElements); 387 } 388 } 389 390 /** 391 * how many bytes are needed when the scalar object is copied by GC? 392 * 393 * @param fromObj the object to copy 394 * @param type the object's type 395 * @return number of needed bytes when the scalar object is copied by GC 396 */ 397 public static int bytesRequiredWhenCopied(Object fromObj, RVMClass type) { 398 return JavaHeader.bytesRequiredWhenCopied(fromObj, type); 399 } 400 401 /** 402 * how many bytes are needed when the array object is copied by GC? 403 * 404 * @param fromObj the object to copy 405 * @param type the object's type 406 * @param numElements the number of elements in the array 407 * @return the number of bytes that are required for the copy 408 */ 409 public static int bytesRequiredWhenCopied(Object fromObj, RVMArray type, int numElements) { 410 return JavaHeader.bytesRequiredWhenCopied(fromObj, type, numElements); 411 } 412 413 /** 414 * Maps from the object ref to the lowest address of the storage 415 * associated with the object. 416 * 417 * @param obj the object reference 418 * @return the lowest address in the object's memory region 419 */ 420 @Inline 421 public static Address objectStartRef(ObjectReference obj) { 422 return JavaHeader.objectStartRef(obj); 423 } 424 425 /** 426 * Get the reference of an object after copying to a specified region. 427 * 428 * @param obj the object to copy 429 * @param region the target address for the copy 430 * @param type the scalar's type 431 * @return the reference of the copy 432 */ 433 public static Object getReferenceWhenCopiedTo(Object obj, Address region, RVMClass type) { 434 return JavaHeader.getReferenceWhenCopiedTo(obj, region, type); 435 } 436 437 /** 438 * Get the reference of an object after copying to a specified region. 439 * 440 * @param obj the object to copy 441 * @param region the target address for the copy 442 * @param type the array's type 443 * @return the reference of the copy 444 */ 445 public static Object getReferenceWhenCopiedTo(Object obj, Address region, RVMArray type) { 446 return JavaHeader.getReferenceWhenCopiedTo(obj, region, type); 447 } 448 449 /** 450 * Copies a scalar object to the given raw storage address. 451 * 452 * @param fromObj the scalar to copy 453 * @param toObj target address for copy 454 * @param numBytes how many bytes to copy 455 * @param type the scalar's type 456 * @return the reference for the object's copy 457 */ 458 public static Object moveObject(Object fromObj, Object toObj, int numBytes, RVMClass type) { 459 return JavaHeader.moveObject(fromObj, toObj, numBytes, type); 460 } 461 462 /** 463 * Copy an array object to the given raw storage address. 464 * 465 * @param fromObj the object to copy 466 * @param toObj the target object 467 * @param numBytes the number of bytes to copy 468 * @param type the array's type 469 * @return the reference for the array's copy 470 */ 471 public static Object moveObject(Object fromObj, Object toObj, int numBytes, RVMArray type) { 472 return JavaHeader.moveObject(fromObj, toObj, numBytes, type); 473 } 474 475 /** 476 * Copy a scalar object to the given raw storage address. 477 * 478 * @param toAddress the target address 479 * @param fromObj the object to copy 480 * @param numBytes how many bytes to copy 481 * @param type the scalar's type 482 * @return the reference for the object's copy 483 */ 484 public static Object moveObject(Address toAddress, Object fromObj, int numBytes, RVMClass type) { 485 return JavaHeader.moveObject(toAddress, fromObj, numBytes, type); 486 } 487 488 /** 489 * Copy an array object to the given raw storage address 490 * 491 * @param toAddress the target address 492 * @param fromObj the object to copy 493 * @param numBytes how many bytes to copy 494 * @param type the array's type 495 * @return the reference for the object's copy 496 */ 497 public static Object moveObject(Address toAddress, Object fromObj, int numBytes, RVMArray type) { 498 return JavaHeader.moveObject(toAddress, fromObj, numBytes, type); 499 } 500 501 /** 502 * @param o an object 503 * @return the type of an object 504 */ 505 public static RVMType getObjectType(Object o) { 506 return Magic.getObjectType(o); 507 } 508 509 /** 510 * @param o an array 511 * @return the length of an array 512 */ 513 public static int getArrayLength(Object o) { 514 return Magic.getIntAtOffset(o, getArrayLengthOffset()); 515 } 516 517 /** 518 * Sets the length of an array. 519 * 520 * @param o an array 521 * @param len the length of the array 522 */ 523 public static void setArrayLength(Object o, int len) { 524 Magic.setIntAtOffset(o, getArrayLengthOffset(), len); 525 } 526 527 @Interruptible 528 public static int getObjectHashCode(Object o) { 529 if (HASH_STATS) hashRequests++; 530 return JavaHeader.getObjectHashCode(o); 531 } 532 533 public static Offset getThinLockOffset(Object o) { 534 return JavaHeader.getThinLockOffset(o); 535 } 536 537 public static Offset defaultThinLockOffset() { 538 return JavaHeader.defaultThinLockOffset(); 539 } 540 541 /** 542 * Allocates a thin lock word for instances of the type 543 * (if they already have one, then has no effect). 544 * 545 * @param t the type that is supposed to receive a thin 546 * lock word 547 */ 548 public static void allocateThinLock(RVMType t) { 549 JavaHeader.allocateThinLock(t); 550 } 551 552 @Entrypoint 553 @Unpreemptible("Become another thread when lock is contended, don't preempt in other cases") 554 public static void genericLock(Object o) { 555 JavaHeader.genericLock(o); 556 } 557 558 @Entrypoint 559 @Unpreemptible("No preemption normally, but may raise exceptions") 560 public static void genericUnlock(Object o) { 561 JavaHeader.genericUnlock(o); 562 } 563 564 /** 565 * @param obj an object 566 * @param thread a thread 567 * @return <code>true</code> if the lock on obj is currently owned 568 * by thread <code>false</code> if it is not. 569 */ 570 public static boolean holdsLock(Object obj, RVMThread thread) { 571 return JavaHeader.holdsLock(obj, thread); 572 } 573 574 /** 575 * Obtains the heavy-weight lock, if there is one, associated with the 576 * indicated object. Returns <code>null</code>, if there is no 577 * heavy-weight lock associated with the object. 578 * 579 * @param o the object from which a lock is desired 580 * @param create if true, create heavy lock if none found 581 * @return the heavy-weight lock on the object (if any) 582 */ 583 @Unpreemptible("May be interrupted for allocations of locks") 584 public static Lock getHeavyLock(Object o, boolean create) { 585 return JavaHeader.getHeavyLock(o, create); 586 } 587 588 /** 589 * Non-atomic read of word containing available bits 590 * 591 * @param o the object to read 592 * @return the available bits word 593 */ 594 public static Word readAvailableBitsWord(Object o) { 595 return JavaHeader.readAvailableBitsWord(o); 596 } 597 598 /** 599 * Non-atomic read of byte containing available bits 600 * @param o the object to read 601 * @return the available bits bytes 602 */ 603 public static byte readAvailableByte(Object o) { 604 return JavaHeader.readAvailableByte(o); 605 } 606 607 /** 608 * Non-atomic write of word containing available bits. 609 * 610 * @param o the object whose word will be written 611 * @param val the available bits word 612 */ 613 public static void writeAvailableBitsWord(Object o, Word val) { 614 JavaHeader.writeAvailableBitsWord(o, val); 615 } 616 617 /** 618 * Non-atomic write of byte containing available bits 619 * 620 * @param o the object whose available byte will be written 621 * @param val the value to write to the available byte 622 */ 623 public static void writeAvailableByte(Object o, byte val) { 624 JavaHeader.writeAvailableByte(o, val); 625 } 626 627 /** 628 * @param o the object whose bit will be tested 629 * @param idx the index in the bits 630 * @return {@code true} if argument bit is 1, {@code false} if it is 0 631 */ 632 public static boolean testAvailableBit(Object o, int idx) { 633 return JavaHeader.testAvailableBit(o, idx); 634 } 635 636 /** 637 * Sets argument bit to 1 if value is true, 0 if value is false 638 * 639 * @param o the object whose bit will be set 640 * @param idx the index in the bits 641 * @param flag {@code true} for 1, {@code false} for 0 642 */ 643 public static void setAvailableBit(Object o, int idx, boolean flag) { 644 JavaHeader.setAvailableBit(o, idx, flag); 645 } 646 647 /** 648 * Freezes the other bits in the byte containing the available bits 649 * so that it is safe to update them using setAvailableBits. 650 * 651 * @param o the object whose available bytes will be initialized 652 */ 653 @Interruptible 654 public static void initializeAvailableByte(Object o) { 655 JavaHeader.initializeAvailableByte(o); 656 } 657 658 /** 659 * A prepare on the word containing the available bits. 660 * <p> 661 * Note: this method is intended to be used in conjunction 662 * with the attempt method. 663 * 664 * @param o the object which has the available bits 665 * @return the current value of the word 666 * @see #attemptAvailableBits(Object, Word, Word) 667 */ 668 public static Word prepareAvailableBits(Object o) { 669 return JavaHeader.prepareAvailableBits(o); 670 } 671 672 /** 673 * An attempt on the word containing the available bits. 674 * <p> 675 * Note: this method is intended to be used in conjunction 676 * with the prepare method. If the method returns {@code false}, 677 * callers must update their information about the old value of 678 * the available bits word before retrying again. 679 * 680 * @param o the object which has the available bits 681 * @param oldVal the old value that the word is expected to have 682 * @param newVal the new value that will be written, if possible 683 * @return whether the write occurred 684 */ 685 public static boolean attemptAvailableBits(Object o, Word oldVal, Word newVal) { 686 return JavaHeader.attemptAvailableBits(o, oldVal, newVal); 687 } 688 689 /** 690 * Given the smallest base address in a region, return the smallest 691 * object reference that could refer to an object in the region. 692 * 693 * @param regionBaseAddr the smallest base address in the region 694 * @return the smallest address in the region that could possibly 695 * refer to an object in the region 696 */ 697 public static Address minimumObjectRef(Address regionBaseAddr) { 698 return JavaHeader.minimumObjectRef(regionBaseAddr); 699 } 700 701 /** 702 * Given the largest base address in a region, return the largest 703 * object reference that could refer to an object in the region. 704 * 705 * @param regionHighAddr the highest base address in the region 706 * @return the largest address in the region that could possibly 707 * refer to an object in the region 708 */ 709 public static Address maximumObjectRef(Address regionHighAddr) { 710 return JavaHeader.maximumObjectRef(regionHighAddr); 711 } 712 713 /** 714 * Computes the header size of an instance of the given type. 715 * 716 * @param type the instance's type 717 * @return size of the head in bytes 718 */ 719 @Inline 720 public static int computeHeaderSize(RVMType type) { 721 if (type.isArrayType()) { 722 return computeArrayHeaderSize(type.asArray()); 723 } else { 724 return computeScalarHeaderSize(type.asClass()); 725 } 726 } 727 728 /** 729 * Computes the header size of an object. 730 * 731 * @param ref the object whose header size is of interest 732 * @return the object's header size 733 */ 734 @Interruptible 735 public static int computeHeaderSize(Object ref) { 736 return computeHeaderSize(getObjectType(ref)); 737 } 738 739 /** 740 * Computes the header size of an instance of the given type. 741 * 742 * @param type the instance's type 743 * @return size of the head in bytes 744 */ 745 @Inline 746 public static int computeScalarHeaderSize(RVMClass type) { 747 return JavaHeader.computeScalarHeaderSize(type); 748 } 749 750 /** 751 * Computes the header size of an instance of the given type. 752 * 753 * @param type the instance's type 754 * @return size of the head in bytes 755 */ 756 public static int computeArrayHeaderSize(RVMArray type) { 757 return JavaHeader.computeArrayHeaderSize(type); 758 } 759 760 /** 761 * Given a TIB, compute the header size of an instance of the TIB's class. 762 * 763 * @param tib a TIB 764 * @return the header size of an object from the class given by the TIB 765 */ 766 public static int computeHeaderSize(Object[] tib) { 767 return computeHeaderSize(Magic.objectAsType(tib[0])); 768 } 769 770 /** 771 * For a reference to an object, what is the offset in bytes to the 772 * last word of the header from an out-to-in perspective for the object? 773 * 774 * @return offset of the last word of the header from an 775 * out-to-in perspective 776 */ 777 public static int getHeaderEndOffset() { 778 return JavaHeader.getHeaderEndOffset(); 779 } 780 781 /** 782 * For a reference to an object, what is the offset in bytes to the bottom 783 * word of the object? 784 * 785 * @param t the class of the object 786 * @return offset of the first word of the class from the object 787 * reference 788 */ 789 public static int objectStartOffset(RVMClass t) { 790 return JavaHeader.objectStartOffset(t); 791 } 792 793 /** 794 * @param t RVMClass instance being created 795 * @return the desired alignment of the alignment point returned by 796 * getOffsetForAlignment in instances of the argument RVMClass. 797 */ 798 public static int getAlignment(RVMClass t) { 799 return JavaHeader.getAlignment(t); 800 } 801 802 /** 803 * @param t RVMClass instance being copied 804 * @param obj the object being copied 805 * @return the desired alignment of the alignment point returned by 806 * getOffsetForAlignment in instances of the argument RVMClass. 807 */ 808 809 public static int getAlignment(RVMClass t, Object obj) { 810 return JavaHeader.getAlignment(t, obj); 811 } 812 813 /** 814 * @param t RVMArray instance being created 815 * @return the desired alignment of the alignment point returned by 816 * getOffsetForAlignment in instances of the argument RVMArray. 817 */ 818 public static int getAlignment(RVMArray t) { 819 return JavaHeader.getAlignment(t); 820 } 821 822 /** 823 * @param t RVMArray instance being copied 824 * @param obj the object being copied 825 * @return the desired alignment of the alignment point returned by 826 * getOffsetForAlignment in instances of the argument RVMArray. 827 */ 828 public static int getAlignment(RVMArray t, Object obj) { 829 return JavaHeader.getAlignment(t, obj); 830 } 831 832 /** 833 * @param t RVMClass instance being created 834 * @param needsIdentityHash TODO document this parameter. IIs it still needed? 835 * It's never set to true. 836 * @return the offset relative to physical beginning of object 837 * that must be aligned. 838 */ 839 public static int getOffsetForAlignment(RVMClass t, boolean needsIdentityHash) { 840 return JavaHeader.getOffsetForAlignment(t, needsIdentityHash); 841 } 842 843 /** 844 * @param t RVMClass instance being copied 845 * @param obj the object being copied 846 * @return the offset relative to physical beginning of object 847 * that must be aligned. 848 */ 849 public static int getOffsetForAlignment(RVMClass t, ObjectReference obj) { 850 return JavaHeader.getOffsetForAlignment(t, obj); 851 } 852 853 /** 854 * @param t RVMArray instance being created 855 * @param needsIdentityHash TODO document this parameter. Is it still needed? 856 * It's never set to true. 857 * @return the offset relative to physical beginning of object that must 858 * be aligned. 859 */ 860 public static int getOffsetForAlignment(RVMArray t, boolean needsIdentityHash) { 861 return JavaHeader.getOffsetForAlignment(t, needsIdentityHash); 862 } 863 864 /** 865 * @param t RVMArray instance being copied 866 * @param obj the object being copied 867 * @return the offset relative to physical beginning of object that must 868 * be aligned. 869 */ 870 public static int getOffsetForAlignment(RVMArray t, ObjectReference obj) { 871 return JavaHeader.getOffsetForAlignment(t, obj); 872 } 873 874 /** 875 * Initialize raw storage with low memory word ptr of size bytes 876 * to be an uninitialized instance of the (scalar) type specified by tib. 877 * 878 * @param ptr address of raw storage 879 * @param tib the type information block 880 * @param size number of bytes of raw storage allocated. 881 * @return the object whose storage was initialized 882 */ 883 @Inline 884 public static Object initializeScalar(Address ptr, TIB tib, int size) { 885 Object ref = JavaHeader.initializeScalarHeader(ptr, tib, size); 886 MiscHeader.initializeHeader(ref, tib, size, true); 887 setTIB(ref, tib); 888 return ref; 889 } 890 891 /** 892 * Allocate and initialize space in the bootimage (at bootimage writing time) 893 * to be an uninitialized instance of the (scalar) type specified by klass. 894 * NOTE: TIB is set by BootImageWriter2 895 * 896 * @param bootImage the bootimage to put the object in 897 * @param klass the RVMClass object of the instance to create. 898 * @param needsIdentityHash needs an identity hash value 899 * @param identityHashValue the value for the identity hash 900 * @return the offset of object in bootimage (in bytes) 901 */ 902 @Interruptible 903 public static Address allocateScalar(BootImageInterface bootImage, RVMClass klass, boolean needsIdentityHash, int identityHashValue) { 904 TIB tib = klass.getTypeInformationBlock(); 905 int size = klass.getInstanceSize(); 906 if (needsIdentityHash) { 907 if (ADDRESS_BASED_HASHING) { 908 size += HASHCODE_BYTES; 909 } else { 910 // TODO: support rehashing or header initialisation for object models 911 // that don't support an extra word for the hash code 912 throw new Error("Unsupported allocation"); 913 } 914 } 915 int align = getAlignment(klass); 916 int offset = getOffsetForAlignment(klass, needsIdentityHash); 917 Address ptr = bootImage.allocateDataStorage(size, align, offset); 918 Address ref = JavaHeader.initializeScalarHeader(bootImage, ptr, tib, size, needsIdentityHash, identityHashValue); 919 MemoryManager.initializeHeader(bootImage, ref, tib, size, true); 920 MiscHeader.initializeHeader(bootImage, ref, tib, size, true); 921 return ref; 922 } 923 924 /** 925 * Fills an alignment gap with the alignment value 926 * 927 * @param bootImage the bootimage being compiled 928 * @param address the start address for the gap that needs to be filled 929 * @param size the size of the gap to be filled 930 */ 931 @Interruptible 932 public static void fillAlignmentGap(BootImageInterface bootImage, Address address, Extent size) { 933 while (size.GT(Extent.zero())) { 934 bootImage.setFullWord(address, JavaHeader.ALIGNMENT_VALUE); 935 address = address.plus(BYTES_IN_INT); 936 size = size.minus(BYTES_IN_INT); 937 } 938 } 939 940 /** 941 * Initialize raw storage with low memory word ptr of size bytes 942 * to be an uninitialized instance of the array type specific by tib 943 * with numElems elements. 944 * 945 * @param ptr address of raw storage 946 * @param tib the type information block 947 * @param numElems number of elements in the array 948 * @param size number of bytes of raw storage allocated. 949 * @return the array whose header was initialized 950 */ 951 @Inline 952 public static Object initializeArray(Address ptr, TIB tib, int numElems, int size) { 953 Object ref = JavaHeader.initializeArrayHeader(ptr, tib, size); 954 MiscHeader.initializeHeader(ref, tib, size, false); 955 setTIB(ref, tib); 956 setArrayLength(ref, numElems); 957 return ref; 958 } 959 960 /** 961 * Allocate and initialize space in the bootimage (at bootimage writing time) 962 * to be an uninitialized instance of the (array) type specified by array. 963 * NOTE: TIB is set by BootimageWriter2 964 * 965 * @param bootImage the bootimage to put the object in 966 * @param array RVMArray object of array being allocated. 967 * @param numElements number of elements 968 * @param needsIdentityHash needs an identity hash value 969 * @param identityHashValue the value for the identity hash 970 * @param alignCode TODO 971 * @return Address of object in bootimage (in bytes) 972 */ 973 @Interruptible 974 public static Address allocateArray(BootImageInterface bootImage, RVMArray array, int numElements, boolean needsIdentityHash, int identityHashValue, int alignCode) { 975 int align = getAlignment(array); 976 return allocateArray(bootImage, array, numElements, needsIdentityHash, identityHashValue, align, alignCode); 977 } 978 979 /** 980 * Allocate and initialize space in the bootimage (at bootimage writing time) 981 * to be an uninitialized instance of the (array) type specified by array. 982 * NOTE: TIB is set by BootimageWriter2 983 * 984 * @param bootImage the bootimage to put the object in 985 * @param array RVMArray object of array being allocated. 986 * @param numElements number of elements 987 * @param needsIdentityHash needs an identity hash value 988 * @param identityHashValue the value for the identity hash 989 * @param align special alignment value 990 * @param alignCode the alignment-encoded value 991 * @return Address of object in bootimage (in bytes) 992 */ 993 @Interruptible 994 public static Address allocateArray(BootImageInterface bootImage, RVMArray array, int numElements, boolean needsIdentityHash, int identityHashValue, int align, int alignCode) { 995 TIB tib = array.getTypeInformationBlock(); 996 int size = array.getInstanceSize(numElements); 997 if (needsIdentityHash) { 998 if (ADDRESS_BASED_HASHING) { 999 size += HASHCODE_BYTES; 1000 } else { 1001 // TODO: support rehashing or header initialisation for object models 1002 // that don't support an extra word for the hash code 1003 throw new Error("Unsupported allocation"); 1004 } 1005 } 1006 int offset = getOffsetForAlignment(array, needsIdentityHash); 1007 int padding = AlignmentEncoding.padding(alignCode); 1008 Address ptr = bootImage.allocateDataStorage(size + padding, align, offset); 1009 ptr = AlignmentEncoding.adjustRegion(alignCode, ptr); 1010 Address ref = JavaHeader.initializeArrayHeader(bootImage, ptr, tib, size, numElements, needsIdentityHash, identityHashValue); 1011 bootImage.setFullWord(ref.plus(getArrayLengthOffset()), numElements); 1012 MemoryManager.initializeHeader(bootImage, ref, tib, size, false); 1013 MiscHeader.initializeHeader(bootImage, ref, tib, size, false); 1014 return ref; 1015 } 1016 1017 /** 1018 * Allocate and initialize space in the bootimage (at bootimage writing time) 1019 * to be an uninitialized instance of the (array) type specified by array. 1020 * NOTE: TIB is set by BootimageWriter2 1021 * 1022 * @param bootImage the bootimage to put the object in 1023 * @param array RVMArray object of array being allocated. 1024 * @param numElements number of elements 1025 * @return Address of object in bootimage 1026 */ 1027 @Interruptible 1028 public static Address allocateCode(BootImageInterface bootImage, RVMArray array, int numElements) { 1029 TIB tib = array.getTypeInformationBlock(); 1030 int size = array.getInstanceSize(numElements); 1031 int align = getAlignment(array); 1032 int offset = getOffsetForAlignment(array, false); 1033 Address ptr = bootImage.allocateCodeStorage(size, align, offset); 1034 Address ref = JavaHeader.initializeArrayHeader(bootImage, ptr, tib, size, numElements, false, 0); 1035 bootImage.setFullWord(ref.plus(getArrayLengthOffset()), numElements); 1036 MemoryManager.initializeHeader(bootImage, ref, tib, size, false); 1037 MiscHeader.initializeHeader(bootImage, ref, tib, size, false); 1038 return ref; 1039 } 1040 1041 /** 1042 * For low level debugging of GC subsystem. 1043 * Dump the header word(s) of the given object reference. 1044 * @param ptr the object reference whose header should be dumped 1045 */ 1046 public static void dumpHeader(ObjectReference ptr) { 1047 dumpHeader(ptr.toObject()); 1048 } 1049 1050 /** 1051 * For low level debugging of GC subsystem. 1052 * Dump the header word(s) of the given object reference. 1053 * @param ref the object reference whose header should be dumped 1054 */ 1055 public static void dumpHeader(Object ref) { 1056 VM.sysWrite(" TIB="); 1057 VM.sysWrite(Magic.objectAsAddress(getTIB(ref))); 1058 JavaHeader.dumpHeader(ref); 1059 MiscHeader.dumpHeader(ref); 1060 } 1061 1062 /** 1063 * For debugging: dumps descriptor of an object. 1064 * 1065 * @param addr the object to dump 1066 */ 1067 public static void describeObject(ObjectReference addr) { 1068 Object obj = addr.toObject(); 1069 RVMType type = Magic.getObjectType(obj); 1070 VM.sysWrite(type.getDescriptor()); 1071 } 1072} 1073 1074