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.objectmodel; 014 015 import org.jikesrvm.ArchitectureSpecific.Assembler; 016 import org.jikesrvm.VM; 017 import org.jikesrvm.SizeConstants; 018 import org.jikesrvm.classloader.RVMArray; 019 import org.jikesrvm.classloader.RVMClass; 020 import org.jikesrvm.classloader.RVMType; 021 import org.jikesrvm.mm.mminterface.AlignmentEncoding; 022 import org.jikesrvm.mm.mminterface.MemoryManager; 023 import org.jikesrvm.runtime.Magic; 024 import org.jikesrvm.scheduler.Lock; 025 import org.jikesrvm.scheduler.RVMThread; 026 import org.vmmagic.pragma.Entrypoint; 027 import org.vmmagic.pragma.Inline; 028 import org.vmmagic.pragma.Interruptible; 029 import org.vmmagic.pragma.Uninterruptible; 030 import org.vmmagic.pragma.Unpreemptible; 031 import org.vmmagic.unboxed.Address; 032 import org.vmmagic.unboxed.Extent; 033 import org.vmmagic.unboxed.ObjectReference; 034 import org.vmmagic.unboxed.Offset; 035 import org.vmmagic.unboxed.Word; 036 037 /** 038 * The interface to the object model definition accessible to the 039 * virtual machine. <p> 040 * 041 * Conceptually each Java object is composed of the following pieces: 042 * <ul> 043 * <li> The JavaHeader defined by {@link JavaHeader}. This portion of the 044 * object supports language-level functions such as locking, hashcodes, 045 * dynamic type checking, virtual function invocation, and array length. 046 * <li> The GCHeader defined by {@link MemoryManager}. This portion 047 * of the object supports allocator-specific requirements such as 048 * mark/barrier bits, reference counts, etc. 049 * <li> The MiscHeader defined by {@link MiscHeader}. This portion supports 050 * various other clients that want to add bits/words to all objects. 051 * Typical uses are profiling and instrumentation (basically this is a 052 * way to add an instance field to java.lang.Object). 053 * <li> The instance fields. Currently defined by various classloader classes. 054 * Factoring this code out and making it possible to lay out the instance 055 * fields in different ways is a todo item. 056 * </ul> 057 * 058 * Every object's header contains the three portions outlined above. 059 * 060 * <pre> 061 * |<- lo memory hi memory ->| 062 * 063 * SCALAR LAYOUT: 064 * |<---------- scalar header --------->| 065 * +----------+------------+------------+------+------+------+--------+ 066 * | GCHeader | MiscHeader | JavaHeader | fldO | fld1 | fldx | fldN-1 | 067 * +----------+------------+------------+------+------+------+--------+ 068 * ^ JHOFF ^objref 069 * . 070 * ARRAY LAYOUT: . 071 * |<---------- array header ----------------->| 072 * +----------+------------+------------+------+------+------+------+------+ 073 * | GCHeader | MiscHeader | JavaHeader | len | elt0 | elt1 | ... |eltN-1| 074 * +----------+------------+------------+------+------+------+------+------+ 075 * ^ JHOFF ^objref 076 * </pre> 077 * <p> 078 * Assumptions: 079 * <ul> 080 * <li> Each portion of the header (JavaHeader, GCHeader, MiscHeader) 081 * is some multiple of 4 bytes (possibly 0). This simplifies access, since we 082 * can access each portion independently without having to worry about word tearing. 083 * <li> The JavaHeader exports k (>=0) unused contiguous bits that can be used 084 * by the GCHeader and MiscHeader. The GCHeader gets first dibs on these bits. 085 * The GCHeader should use buts 0..i, MiscHeader should use bits i..k. 086 * <li> JHOFF is a constant for a given configuration. 087 * </ul> 088 * 089 * This model allows efficient array access: the array pointer can be 090 * used directly in the base+offset subscript calculation, with no 091 * additional constant required.<p> 092 * 093 * This model allows free null pointer checking for most reads: a 094 * small offset from that reference will wrap around to either very 095 * high or very low unmapped memory in the case of a null pointer. As 096 * long as these segments of memory are not mapped to the current 097 * process, loads/stores through such a pointer will cause a trap that 098 * we can catch with a unix signal handler.<p> 099 * 100 * Note that on AIX we are forced to perform explicit null checks on 101 * scalar field accesses as we are unable to protect low memory.<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 129 public class ObjectModel implements JavaHeaderConstants, SizeConstants { 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 public static Address getPointerInMemoryRegion(ObjectReference ref) { 168 return JavaHeader.getPointerInMemoryRegion(ref); 169 } 170 171 /** 172 * Return the offset of the array length field from an object reference 173 * (in bytes) 174 */ 175 public static Offset getArrayLengthOffset() { 176 return ARRAY_LENGTH_OFFSET; 177 } 178 179 /** 180 * Get the TIB for an object. 181 */ 182 public static TIB getTIB(ObjectReference ptr) { 183 return getTIB(ptr.toObject()); 184 } 185 186 /** 187 * Get the TIB for an object. 188 */ 189 public static TIB getTIB(Object o) { 190 return JavaHeader.getTIB(o); 191 } 192 193 /** 194 * Set the TIB for an object. 195 */ 196 public static void setTIB(ObjectReference ptr, TIB tib) { 197 setTIB(ptr.toObject(), tib); 198 } 199 200 /** 201 * Set the TIB for an object. 202 */ 203 public static void setTIB(Object ref, TIB tib) { 204 JavaHeader.setTIB(ref, tib); 205 } 206 207 /** 208 * Set the TIB for an object. 209 */ 210 @Interruptible 211 public static void setTIB(BootImageInterface bootImage, Address refAddress, Address tibAddr, RVMType type) { 212 JavaHeader.setTIB(bootImage, refAddress, tibAddr, type); 213 } 214 215 /** 216 * Get the pointer just past an 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 * Get the pointer just past an object 231 */ 232 public static Address getObjectEndAddress(Object object, RVMClass type) { 233 return JavaHeader.getObjectEndAddress(object, type); 234 } 235 236 /** 237 * Get the pointer just past an object 238 */ 239 public static Address getObjectEndAddress(Object object, RVMArray type, int elements) { 240 return JavaHeader.getObjectEndAddress(object, type, elements); 241 } 242 243 /** 244 * Get an object reference from the address the lowest word of the object was allocated. 245 */ 246 public static ObjectReference getObjectFromStartAddress(Address start) { 247 return JavaHeader.getObjectFromStartAddress(start); 248 } 249 250 /** 251 * Get an object reference from the address the lowest word of the object was allocated. 252 */ 253 public static ObjectReference getScalarFromStartAddress(Address start) { 254 return JavaHeader.getScalarFromStartAddress(start); 255 } 256 257 /** 258 * Get an object reference from the address the lowest word of the object was allocated. 259 */ 260 public static ObjectReference getArrayFromStartAddress(Address start) { 261 return JavaHeader.getArrayFromStartAddress(start); 262 } 263 264 /** 265 * Get the next object in the heap under contiguous allocation. 266 */ 267 public static ObjectReference getNextObject(ObjectReference obj) { 268 TIB tib = getTIB(obj); 269 RVMType type = tib.getType(); 270 if (type.isClassType()) { 271 return getNextObject(obj, type.asClass()); 272 } else { 273 int numElements = Magic.getArrayLength(obj); 274 return getNextObject(obj, type.asArray(), numElements); 275 } 276 } 277 278 /** 279 * Get the next object after this scalar under contiguous allocation. 280 */ 281 public static ObjectReference getNextObject(ObjectReference obj, RVMClass type) { 282 return JavaHeader.getNextObject(obj, type); 283 } 284 285 /** 286 * Get the next object after this array under contiguous allocation. 287 */ 288 public static ObjectReference getNextObject(ObjectReference obj, RVMArray type, int numElements) { 289 return JavaHeader.getNextObject(obj, type, numElements); 290 } 291 292 /** 293 * how many bytes are used by the object? 294 */ 295 public static Object getReferenceWhenCopiedTo(Object obj, Address to) { 296 TIB tib = getTIB(obj); 297 RVMType type = tib.getType(); 298 if (type.isClassType()) { 299 return getReferenceWhenCopiedTo(obj, to, type.asClass()); 300 } else { 301 return getReferenceWhenCopiedTo(obj, to, type.asArray()); 302 } 303 } 304 305 /** 306 * how many bytes are used by the object? 307 */ 308 public static int bytesUsed(Object obj) { 309 TIB tib = getTIB(obj); 310 RVMType type = tib.getType(); 311 if (type.isClassType()) { 312 return bytesUsed(obj, type.asClass()); 313 } else { 314 int numElements = Magic.getArrayLength(obj); 315 return bytesUsed(obj, type.asArray(), numElements); 316 } 317 } 318 319 /** 320 * how many bytes are used by the scalar? 321 */ 322 public static int bytesUsed(Object obj, RVMClass type) { 323 return JavaHeader.bytesUsed(obj, type); 324 } 325 326 /** 327 * how many bytes are used by the array? 328 */ 329 public static int bytesUsed(Object obj, RVMArray type, int numElements) { 330 return JavaHeader.bytesUsed(obj, type, numElements); 331 } 332 333 /** 334 * how many bytes are required when the object is copied by GC? 335 */ 336 public static int bytesRequiredWhenCopied(Object obj) { 337 TIB tib = getTIB(obj); 338 RVMType type = tib.getType(); 339 if (type.isClassType()) { 340 return bytesRequiredWhenCopied(obj, type.asClass()); 341 } else { 342 int numElements = Magic.getArrayLength(obj); 343 return bytesRequiredWhenCopied(obj, type.asArray(), numElements); 344 } 345 } 346 347 /** 348 * how many bytes are needed when the scalar object is copied by GC? 349 */ 350 public static int bytesRequiredWhenCopied(Object fromObj, RVMClass type) { 351 return JavaHeader.bytesRequiredWhenCopied(fromObj, type); 352 } 353 354 /** 355 * how many bytes are needed when the array object is copied by GC? 356 */ 357 public static int bytesRequiredWhenCopied(Object fromObj, RVMArray type, int numElements) { 358 return JavaHeader.bytesRequiredWhenCopied(fromObj, type, numElements); 359 } 360 361 /** 362 * Map from the object ref to the lowest address of the storage 363 * associated with the object 364 */ 365 @Inline 366 public static Address objectStartRef(ObjectReference obj) { 367 return JavaHeader.objectStartRef(obj); 368 } 369 370 /** 371 * Get the reference of an object after copying to a specified region. 372 */ 373 public static Object getReferenceWhenCopiedTo(Object obj, Address region, RVMClass type) { 374 return JavaHeader.getReferenceWhenCopiedTo(obj, region, type); 375 } 376 377 /** 378 * Get the reference of an object after copying to a specified region. 379 */ 380 public static Object getReferenceWhenCopiedTo(Object obj, Address region, RVMArray type) { 381 return JavaHeader.getReferenceWhenCopiedTo(obj, region, type); 382 } 383 384 /** 385 * Copy a scalar object to the given raw storage address 386 */ 387 public static Object moveObject(Object fromObj, Object toObj, int numBytes, RVMClass type) { 388 return JavaHeader.moveObject(fromObj, toObj, numBytes, type); 389 } 390 391 /** 392 * Copy an array object to the given raw storage address 393 */ 394 public static Object moveObject(Object fromObj, Object toObj, int numBytes, RVMArray type) { 395 return JavaHeader.moveObject(fromObj, toObj, numBytes, type); 396 } 397 398 /** 399 * Copy a scalar object to the given raw storage address 400 */ 401 public static Object moveObject(Address toAddress, Object fromObj, int numBytes, RVMClass type) { 402 return JavaHeader.moveObject(toAddress, fromObj, numBytes, type); 403 } 404 405 /** 406 * Copy an array object to the given raw storage address 407 */ 408 public static Object moveObject(Address toAddress, Object fromObj, int numBytes, RVMArray type) { 409 return JavaHeader.moveObject(toAddress, fromObj, numBytes, type); 410 } 411 412 /** 413 * Get the type of an object. 414 */ 415 public static RVMType getObjectType(Object o) { 416 return Magic.getObjectType(o); 417 } 418 419 /** 420 * Get the length of an array 421 */ 422 public static int getArrayLength(Object o) { 423 return Magic.getIntAtOffset(o, getArrayLengthOffset()); 424 } 425 426 /** 427 * Set the length of an array 428 */ 429 public static void setArrayLength(Object o, int len) { 430 Magic.setIntAtOffset(o, getArrayLengthOffset(), len); 431 } 432 433 /** 434 * Get the hash code of an object. 435 */ 436 @Interruptible 437 public static int getObjectHashCode(Object o) { 438 if (HASH_STATS) hashRequests++; 439 return JavaHeader.getObjectHashCode(o); 440 } 441 442 /** 443 * Get the offset of the thin lock word in this object 444 */ 445 public static Offset getThinLockOffset(Object o) { 446 return JavaHeader.getThinLockOffset(o); 447 } 448 449 /** 450 * what is the default offset for a thin lock? 451 */ 452 public static Offset defaultThinLockOffset() { 453 return JavaHeader.defaultThinLockOffset(); 454 } 455 456 /** 457 * Allocate a thin lock word for instances of the type 458 * (if they already have one, then has no effect). 459 */ 460 public static void allocateThinLock(RVMType t) { 461 JavaHeader.allocateThinLock(t); 462 } 463 464 /** 465 * Generic lock 466 */ 467 @Entrypoint 468 @Unpreemptible("Become another thread when lock is contended, don't preempt in other cases") 469 public static void genericLock(Object o) { 470 JavaHeader.genericLock(o); 471 } 472 473 /** 474 * Generic unlock 475 */ 476 @Entrypoint 477 @Unpreemptible("No preemption normally, but may raise exceptions") 478 public static void genericUnlock(Object o) { 479 JavaHeader.genericUnlock(o); 480 } 481 482 /** 483 * @param obj an object 484 * @param thread a thread 485 * @return <code>true</code> if the lock on obj is currently owned 486 * by thread <code>false</code> if it is not. 487 */ 488 public static boolean holdsLock(Object obj, RVMThread thread) { 489 return JavaHeader.holdsLock(obj, thread); 490 } 491 492 /** 493 * Obtains the heavy-weight lock, if there is one, associated with the 494 * indicated object. Returns <code>null</code>, if there is no 495 * heavy-weight lock associated with the object. 496 * 497 * @param o the object from which a lock is desired 498 * @param create if true, create heavy lock if none found 499 * @return the heavy-weight lock on the object (if any) 500 */ 501 @Unpreemptible("May be interrupted for allocations of locks") 502 public static Lock getHeavyLock(Object o, boolean create) { 503 return JavaHeader.getHeavyLock(o, create); 504 } 505 506 /** 507 * Non-atomic read of word containing available bits 508 */ 509 public static Word readAvailableBitsWord(Object o) { 510 return JavaHeader.readAvailableBitsWord(o); 511 } 512 513 /** 514 * Non-atomic read of byte containing available bits 515 */ 516 public static byte readAvailableByte(Object o) { 517 return JavaHeader.readAvailableByte(o); 518 } 519 520 /** 521 * Non-atomic write of word containing available bits 522 */ 523 public static void writeAvailableBitsWord(Object o, Word val) { 524 JavaHeader.writeAvailableBitsWord(o, val); 525 } 526 527 /** 528 * Non-atomic write of byte containing available bits 529 */ 530 public static void writeAvailableByte(Object o, byte val) { 531 JavaHeader.writeAvailableByte(o, val); 532 } 533 534 /** 535 * Return true if argument bit is 1, false if it is 0 536 */ 537 public static boolean testAvailableBit(Object o, int idx) { 538 return JavaHeader.testAvailableBit(o, idx); 539 } 540 541 /** 542 * Set argument bit to 1 if flag is true, 0 if flag is false 543 */ 544 public static void setAvailableBit(Object o, int idx, boolean flag) { 545 JavaHeader.setAvailableBit(o, idx, flag); 546 } 547 548 /** 549 * Freeze the other bits in the byte containing the available bits 550 * so that it is safe to update them using setAvailableBits. 551 */ 552 @Interruptible 553 public static void initializeAvailableByte(Object o) { 554 JavaHeader.initializeAvailableByte(o); 555 } 556 557 /** 558 * A prepare on the word containing the available bits 559 */ 560 public static Word prepareAvailableBits(Object o) { 561 return JavaHeader.prepareAvailableBits(o); 562 } 563 564 /** 565 * An attempt on the word containing the available bits 566 */ 567 public static boolean attemptAvailableBits(Object o, Word oldVal, Word newVal) { 568 return JavaHeader.attemptAvailableBits(o, oldVal, newVal); 569 } 570 571 /** 572 * Given the smallest base address in a region, return the smallest 573 * object reference that could refer to an object in the region. 574 */ 575 public static Address minimumObjectRef(Address regionBaseAddr) { 576 return JavaHeader.minimumObjectRef(regionBaseAddr); 577 } 578 579 /** 580 * Given the largest base address in a region, return the largest 581 * object reference that could refer to an object in the region. 582 */ 583 public static Address maximumObjectRef(Address regionHighAddr) { 584 return JavaHeader.maximumObjectRef(regionHighAddr); 585 } 586 587 /** 588 * Compute the header size of an instance of the given type. 589 */ 590 @Inline 591 public static int computeHeaderSize(RVMType type) { 592 if (type.isArrayType()) { 593 return computeArrayHeaderSize(type.asArray()); 594 } else { 595 return computeScalarHeaderSize(type.asClass()); 596 } 597 } 598 599 /** 600 * Compute the header size of an object 601 */ 602 @Interruptible 603 public static int computeHeaderSize(Object ref) { 604 return computeHeaderSize(getObjectType(ref)); 605 } 606 607 /** 608 * Compute the header size of an instance of the given type. 609 */ 610 @Inline 611 public static int computeScalarHeaderSize(RVMClass type) { 612 return JavaHeader.computeScalarHeaderSize(type); 613 } 614 615 /** 616 * Compute the header size of an instance of the given type. 617 */ 618 public static int computeArrayHeaderSize(RVMArray type) { 619 return JavaHeader.computeArrayHeaderSize(type); 620 } 621 622 /** 623 * Given a TIB, compute the header size of an instance of the TIB's class 624 */ 625 public static int computeHeaderSize(Object[] tib) { 626 return computeHeaderSize(Magic.objectAsType(tib[0])); 627 } 628 629 /** 630 * For a reference to an object, what is the offset in bytes to the 631 * last word of the header from an out-to-in perspective for the object? 632 */ 633 public static int getHeaderEndOffset() { 634 return JavaHeader.getHeaderEndOffset(); 635 } 636 637 /** 638 * For a reference to an object, what is the offset in bytes to the bottom 639 * word of the object? 640 */ 641 public static int objectStartOffset(RVMClass t) { 642 return JavaHeader.objectStartOffset(t); 643 } 644 645 /** 646 * Return the desired aligment of the alignment point in the object returned 647 * by getScalarOffsetForAlignment. 648 * @param t RVMClass instance being created 649 */ 650 public static int getAlignment(RVMClass t) { 651 return JavaHeader.getAlignment(t); 652 } 653 654 /** 655 * Return the desired alignment of the alignment point returned by 656 * getOffsetForAlignment in instances of the argument RVMClass. 657 * @param t RVMClass instance being copied 658 * @param obj the object being copied 659 */ 660 public static int getAlignment(RVMClass t, Object obj) { 661 return JavaHeader.getAlignment(t, obj); 662 } 663 664 /** 665 * Return the desired alignment of the alignment point returned by 666 * getOffsetForAlignment in instances of the argument RVMArray. 667 * @param t RVMArray instance being created 668 */ 669 public static int getAlignment(RVMArray t) { 670 return JavaHeader.getAlignment(t); 671 } 672 673 /** 674 * Return the desired alignment of the alignment point returned by 675 * getOffsetForAlignment in instances of the argument RVMArray. 676 * @param t RVMArray instance being copied 677 * @param obj the object being copied 678 */ 679 public static int getAlignment(RVMArray t, Object obj) { 680 return JavaHeader.getAlignment(t, obj); 681 } 682 683 /** 684 * Return the offset relative to physical beginning of object 685 * that must be aligned. 686 * @param t RVMClass instance being created 687 */ 688 public static int getOffsetForAlignment(RVMClass t, boolean needsIdentityHash) { 689 return JavaHeader.getOffsetForAlignment(t, needsIdentityHash); 690 } 691 692 /** 693 * Return the offset relative to physical beginning of object 694 * that must be aligned. 695 * @param t RVMClass instance being copied 696 * @param obj the object being copied 697 */ 698 public static int getOffsetForAlignment(RVMClass t, ObjectReference obj) { 699 return JavaHeader.getOffsetForAlignment(t, obj); 700 } 701 702 /** 703 * Return the offset relative to physical beginning of object that must 704 * be aligned. 705 * @param t RVMArray instance being created 706 */ 707 public static int getOffsetForAlignment(RVMArray t, boolean needsIdentityHash) { 708 return JavaHeader.getOffsetForAlignment(t, needsIdentityHash); 709 } 710 711 /** 712 * Return the offset relative to physical beginning of object that must 713 * be aligned. 714 * @param t RVMArray instance being copied 715 * @param obj the object being copied 716 */ 717 public static int getOffsetForAlignment(RVMArray t, ObjectReference obj) { 718 return JavaHeader.getOffsetForAlignment(t, obj); 719 } 720 721 /** 722 * Initialize raw storage with low memory word ptr of size bytes 723 * to be an uninitialized instance of the (scalar) type specified by tib. 724 * 725 * @param ptr address of raw storage 726 * @param tib the type information block 727 * @param size number of bytes of raw storage allocated. 728 */ 729 @Inline 730 public static Object initializeScalar(Address ptr, TIB tib, int size) { 731 Object ref = JavaHeader.initializeScalarHeader(ptr, tib, size); 732 MiscHeader.initializeHeader(ref, tib, size, true); 733 setTIB(ref, tib); 734 return ref; 735 } 736 737 /** 738 * Allocate and initialize space in the bootimage (at bootimage writing time) 739 * to be an uninitialized instance of the (scalar) type specified by klass. 740 * NOTE: TIB is set by BootImageWriter2 741 * 742 * @param bootImage the bootimage to put the object in 743 * @param klass the RVMClass object of the instance to create. 744 * @param needsIdentityHash needs an identity hash value 745 * @param identityHashValue the value for the identity hash 746 * @return the offset of object in bootimage (in bytes) 747 */ 748 @Interruptible 749 public static Address allocateScalar(BootImageInterface bootImage, RVMClass klass, boolean needsIdentityHash, int identityHashValue) { 750 TIB tib = klass.getTypeInformationBlock(); 751 int size = klass.getInstanceSize(); 752 if (needsIdentityHash) { 753 if (JavaHeader.ADDRESS_BASED_HASHING) { 754 size += JavaHeader.HASHCODE_BYTES; 755 } else { 756 // TODO: support rehashing or header initialisation for object models 757 // that don't support an extra word for the hash code 758 throw new Error("Unsupported allocation"); 759 } 760 } 761 int align = getAlignment(klass); 762 int offset = getOffsetForAlignment(klass, needsIdentityHash); 763 Address ptr = bootImage.allocateDataStorage(size, align, offset); 764 Address ref = JavaHeader.initializeScalarHeader(bootImage, ptr, tib, size, needsIdentityHash, identityHashValue); 765 MemoryManager.initializeHeader(bootImage, ref, tib, size, true); 766 MiscHeader.initializeHeader(bootImage, ref, tib, size, true); 767 return ref; 768 } 769 770 /** 771 * Fill an alignment gap with the alignment value 772 */ 773 @Interruptible 774 public static void fillAlignmentGap(BootImageInterface bootImage, Address address, Extent size) { 775 while (size.GT(Extent.zero())) { 776 bootImage.setFullWord(address, JavaHeader.ALIGNMENT_VALUE); 777 address = address.plus(BYTES_IN_INT); 778 size = size.minus(BYTES_IN_INT); 779 } 780 } 781 782 /** 783 * Initialize raw storage with low memory word ptr of size bytes 784 * to be an uninitialized instance of the array type specific by tib 785 * with numElems elements. 786 * 787 * @param ptr address of raw storage 788 * @param tib the type information block 789 * @param numElems number of elements in the array 790 * @param size number of bytes of raw storage allocated. 791 */ 792 @Inline 793 public static Object initializeArray(Address ptr, TIB tib, int numElems, int size) { 794 Object ref = JavaHeader.initializeArrayHeader(ptr, tib, size); 795 MiscHeader.initializeHeader(ref, tib, size, false); 796 setTIB(ref, tib); 797 setArrayLength(ref, numElems); 798 return ref; 799 } 800 801 /** 802 * Allocate and initialize space in the bootimage (at bootimage writing time) 803 * to be an uninitialized instance of the (array) type specified by array. 804 * NOTE: TIB is set by BootimageWriter2 805 * 806 * @param bootImage the bootimage to put the object in 807 * @param array RVMArray object of array being allocated. 808 * @param numElements number of elements 809 * @param needsIdentityHash needs an identity hash value 810 * @param identityHashValue the value for the identity hash 811 * @param alignCode TODO 812 * @return Address of object in bootimage (in bytes) 813 */ 814 @Interruptible 815 public static Address allocateArray(BootImageInterface bootImage, RVMArray array, int numElements, boolean needsIdentityHash, int identityHashValue, int alignCode) { 816 int align = getAlignment(array); 817 return allocateArray(bootImage, array, numElements, needsIdentityHash, identityHashValue, align, alignCode); 818 } 819 820 /** 821 * Allocate and initialize space in the bootimage (at bootimage writing time) 822 * to be an uninitialized instance of the (array) type specified by array. 823 * NOTE: TIB is set by BootimageWriter2 824 * 825 * @param bootImage the bootimage to put the object in 826 * @param array RVMArray object of array being allocated. 827 * @param numElements number of elements 828 * @param needsIdentityHash needs an identity hash value 829 * @param identityHashValue the value for the identity hash 830 * @param alignCode TODO 831 * @return Address of object in bootimage (in bytes) 832 */ 833 @Interruptible 834 public static Address allocateArray(BootImageInterface bootImage, RVMArray array, int numElements, boolean needsIdentityHash, int identityHashValue, int align, int alignCode) { 835 TIB tib = array.getTypeInformationBlock(); 836 int size = array.getInstanceSize(numElements); 837 if (needsIdentityHash) { 838 if (JavaHeader.ADDRESS_BASED_HASHING) { 839 size += JavaHeader.HASHCODE_BYTES; 840 } else { 841 // TODO: support rehashing or header initialisation for object models 842 // that don't support an extra word for the hash code 843 throw new Error("Unsupported allocation"); 844 } 845 } 846 int offset = getOffsetForAlignment(array, needsIdentityHash); 847 int padding = AlignmentEncoding.padding(alignCode); 848 Address ptr = bootImage.allocateDataStorage(size + padding, align, offset); 849 ptr = AlignmentEncoding.adjustRegion(alignCode, ptr); 850 Address ref = JavaHeader.initializeArrayHeader(bootImage, ptr, tib, size, numElements, needsIdentityHash, identityHashValue); 851 bootImage.setFullWord(ref.plus(getArrayLengthOffset()), numElements); 852 MemoryManager.initializeHeader(bootImage, ref, tib, size, false); 853 MiscHeader.initializeHeader(bootImage, ref, tib, size, false); 854 return ref; 855 } 856 857 /** 858 * Allocate and initialize space in the bootimage (at bootimage writing time) 859 * to be an uninitialized instance of the (array) type specified by array. 860 * NOTE: TIB is set by BootimageWriter2 861 * 862 * @param bootImage the bootimage to put the object in 863 * @param array RVMArray object of array being allocated. 864 * @param numElements number of elements 865 * @return Address of object in bootimage 866 */ 867 @Interruptible 868 public static Address allocateCode(BootImageInterface bootImage, RVMArray array, int numElements) { 869 TIB tib = array.getTypeInformationBlock(); 870 int size = array.getInstanceSize(numElements); 871 int align = getAlignment(array); 872 int offset = getOffsetForAlignment(array, false); 873 Address ptr = bootImage.allocateCodeStorage(size, align, offset); 874 Address ref = JavaHeader.initializeArrayHeader(bootImage, ptr, tib, size, numElements, false, 0); 875 bootImage.setFullWord(ref.plus(getArrayLengthOffset()), numElements); 876 MemoryManager.initializeHeader(bootImage, ref, tib, size, false); 877 MiscHeader.initializeHeader(bootImage, ref, tib, size, false); 878 return ref; 879 } 880 881 /** 882 * For low level debugging of GC subsystem. 883 * Dump the header word(s) of the given object reference. 884 * @param ptr the object reference whose header should be dumped 885 */ 886 public static void dumpHeader(ObjectReference ptr) { 887 dumpHeader(ptr.toObject()); 888 } 889 890 /** 891 * For low level debugging of GC subsystem. 892 * Dump the header word(s) of the given object reference. 893 * @param ref the object reference whose header should be dumped 894 */ 895 public static void dumpHeader(Object ref) { 896 VM.sysWrite(" TIB="); 897 VM.sysWrite(Magic.objectAsAddress(getTIB(ref))); 898 JavaHeader.dumpHeader(ref); 899 MiscHeader.dumpHeader(ref); 900 } 901 902 /** 903 * For debugging. 904 */ 905 public static void describeObject(ObjectReference addr) { 906 Object obj = addr.toObject(); 907 RVMType type = Magic.getObjectType(obj); 908 VM.sysWrite(type.getDescriptor()); 909 } 910 911 /** 912 * The following method will emit code that moves a reference to an 913 * object's TIB into a destination register. 914 * 915 * @param asm the assembler object to emit code with 916 * @param dest the number of the destination register 917 * @param object the number of the register holding the object reference 918 */ 919 @Interruptible 920 public static void baselineEmitLoadTIB(Assembler asm, int dest, int object) { 921 JavaHeader.baselineEmitLoadTIB(asm, dest, object); 922 } 923 } 924 925