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