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 * |&lt;- lo memory                                        hi memory -&gt;|
065 *
066 *   SCALAR LAYOUT:
067 * |&lt;---------- scalar header ---------&gt;|
068 * +----------+------------+------------+------+------+------+--------+
069 * | GCHeader | MiscHeader | JavaHeader | fldO | fld1 | fldx | fldN-1 |
070 * +----------+------------+------------+------+------+------+--------+
071 *                         ^ JHOFF             ^objref
072 *                                             .
073 *    ARRAY LAYOUT:                            .
074 * |&lt;---------- array header -----------------&gt;|
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 (&gt;=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