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.mm.mminterface.MemoryManagerConstants.GENERATE_GC_TRACE;
016import static org.jikesrvm.objectmodel.JavaHeaderConstants.MISC_HEADER_OFFSET;
017import static org.jikesrvm.objectmodel.MiscHeaderConstants.GC_TRACING_HEADER_BYTES;
018import static org.jikesrvm.objectmodel.MiscHeaderConstants.NUM_BYTES_HEADER;
019import static org.jikesrvm.runtime.UnboxedSizeConstants.BYTES_IN_ADDRESS;
020import static org.jikesrvm.runtime.UnboxedSizeConstants.LOG_BYTES_IN_ADDRESS;
021
022import org.jikesrvm.VM;
023import org.jikesrvm.runtime.Magic;
024import org.vmmagic.pragma.Entrypoint;
025import org.vmmagic.pragma.Interruptible;
026import org.vmmagic.pragma.Uninterruptible;
027import org.vmmagic.unboxed.Address;
028import org.vmmagic.unboxed.ObjectReference;
029import org.vmmagic.unboxed.Offset;
030import org.vmmagic.unboxed.Word;
031
032/**
033 * Defines other header words not used for
034 * core Java language support of memory allocation.
035 * Typically these are extra header words used for various
036 * kinds of instrumentation or profiling.
037 *
038 * @see ObjectModel
039 */
040@Uninterruptible
041public final class MiscHeader {
042
043  private static final Offset MISC_HEADER_START = MISC_HEADER_OFFSET;
044
045  /* offset from object ref to .oid field, in bytes */
046  static final Offset OBJECT_OID_OFFSET = MISC_HEADER_START;
047  /* offset from object ref to OBJECT_DEATH field, in bytes */
048  static final Offset OBJECT_DEATH_OFFSET = OBJECT_OID_OFFSET.plus(BYTES_IN_ADDRESS);
049  /* offset from object ref to .link field, in bytes */
050  static final Offset OBJECT_LINK_OFFSET = OBJECT_DEATH_OFFSET.plus(BYTES_IN_ADDRESS);
051
052  /////////////////////////
053  // Support for YYY (an example of how to add a word to all objects)
054  /////////////////////////
055  // offset from object ref to yet-to-be-defined instrumentation word
056  // static final int YYY_DATA_OFFSET_1 = (VM.YYY ? MISC_HEADER_START + GC_TRACING_HEADER_WORDS : 0);
057  // static final int YYY_DATA_OFFSET_2 = (VM.YYY ? MISC_HEADER_START + GC_TRACING_HEADER_WORDS + 4 : 0);
058  // static final int YYY_HEADER_BYTES = (VM.YYY ? 8 : 0);
059
060  /**
061   * How many available bits does the misc header want to use?
062   */
063  static final int REQUESTED_BITS = 0;
064
065  /**
066   * The next object ID to be used.
067   */
068  @Entrypoint
069  private static Word oid;
070  /**
071   * The current "time" for the trace being generated.
072   */
073  private static Word time;
074  /**
075   * The address of the last object allocated into the header.
076   */
077  @Entrypoint
078  private static Word prevAddress;
079
080  static {
081    oid = Word.fromIntSignExtend(4);
082    time = Word.fromIntSignExtend(4);
083    prevAddress = Word.zero();
084  }
085
086  /**
087   * Perform any required initialization of the MISC portion of the header.
088   * @param obj the object ref to the storage to be initialized
089   * @param tib the TIB of the instance being created
090   * @param size the number of bytes allocated by the GC system for this object.
091   * @param isScalar are we initializing a scalar (true) or array (false) object?
092   */
093  @Uninterruptible
094  public static void initializeHeader(Object obj, TIB tib, int size, boolean isScalar) {
095    /* Only perform initialization when it is required */
096    if (GENERATE_GC_TRACE) {
097      Address ref = Magic.objectAsAddress(obj);
098      ref.store(oid, OBJECT_OID_OFFSET);
099      ref.store(time, OBJECT_DEATH_OFFSET);
100      oid = oid.plus(Word.fromIntSignExtend((size - GC_TRACING_HEADER_BYTES) >> LOG_BYTES_IN_ADDRESS));
101    }
102  }
103
104  /**
105   * Perform any required initialization of the MISC portion of the header.
106   * @param bootImage the bootimage being written
107   * @param ref the object ref to the storage to be initialized
108   * @param tib the TIB of the instance being created
109   * @param size the number of bytes allocated by the GC system for this object.
110   * @param isScalar are we initializing a scalar (true) or array (false) object?
111   */
112  @Interruptible("Only called during boot iamge creation")
113  public static void initializeHeader(BootImageInterface bootImage, Address ref, TIB tib, int size,
114                                      boolean isScalar) {
115    /* Only perform initialization when it is required */
116    if (GENERATE_GC_TRACE) {
117      bootImage.setAddressWord(ref.plus(OBJECT_OID_OFFSET), oid, false, false);
118      bootImage.setAddressWord(ref.plus(OBJECT_DEATH_OFFSET), time, false, false);
119      bootImage.setAddressWord(ref.plus(OBJECT_LINK_OFFSET), prevAddress, false, false);
120      prevAddress = ref.toWord();
121      oid = oid.plus(Word.fromIntSignExtend((size - GC_TRACING_HEADER_BYTES) >> LOG_BYTES_IN_ADDRESS));
122    }
123  }
124
125  public static void updateDeathTime(Object object) {
126    if (VM.VerifyAssertions) VM._assert(GENERATE_GC_TRACE);
127    if (GENERATE_GC_TRACE) {
128      Magic.objectAsAddress(object).store(time, OBJECT_DEATH_OFFSET);
129    }
130  }
131
132  public static void setDeathTime(Object object, Word time_) {
133    if (VM.VerifyAssertions) VM._assert(GENERATE_GC_TRACE);
134    if (GENERATE_GC_TRACE) {
135      Magic.objectAsAddress(object).store(time_, OBJECT_DEATH_OFFSET);
136    }
137  }
138
139  public static void setLink(Object object, ObjectReference link) {
140    if (VM.VerifyAssertions) VM._assert(GENERATE_GC_TRACE);
141    if (GENERATE_GC_TRACE) {
142      Magic.objectAsAddress(object).store(link, OBJECT_LINK_OFFSET);
143    }
144  }
145
146  public static void updateTime(Word time_) {
147    if (VM.VerifyAssertions) VM._assert(GENERATE_GC_TRACE);
148    time = time_;
149  }
150
151  public static Word getOID(Object object) {
152    if (VM.VerifyAssertions) VM._assert(GENERATE_GC_TRACE);
153    if (GENERATE_GC_TRACE) {
154      return Magic.objectAsAddress(object).plus(OBJECT_OID_OFFSET).loadWord();
155    } else {
156      return Word.zero();
157    }
158  }
159
160  public static Word getDeathTime(Object object) {
161    if (VM.VerifyAssertions) VM._assert(GENERATE_GC_TRACE);
162    if (GENERATE_GC_TRACE) {
163      return Magic.objectAsAddress(object).plus(OBJECT_DEATH_OFFSET).loadWord();
164    } else {
165      return Word.zero();
166    }
167  }
168
169  public static ObjectReference getLink(Object ref) {
170    if (VM.VerifyAssertions) VM._assert(GENERATE_GC_TRACE);
171    if (GENERATE_GC_TRACE) {
172      return ObjectReference.fromObject(Magic.getObjectAtOffset(ref, OBJECT_LINK_OFFSET));
173    } else {
174      return ObjectReference.nullReference();
175    }
176  }
177
178  public static Address getBootImageLink() {
179    if (VM.VerifyAssertions) VM._assert(GENERATE_GC_TRACE);
180    if (GENERATE_GC_TRACE) {
181      return prevAddress.toAddress();
182    } else {
183      return Address.zero();
184    }
185  }
186
187  public static Word getOID() {
188    if (VM.VerifyAssertions) VM._assert(GENERATE_GC_TRACE);
189    if (GENERATE_GC_TRACE) {
190      return oid;
191    } else {
192      return Word.zero();
193    }
194  }
195
196  public static void setOID(Word oid_) {
197    if (VM.VerifyAssertions) VM._assert(GENERATE_GC_TRACE);
198    if (GENERATE_GC_TRACE) {
199      oid = oid_;
200    }
201  }
202
203  public static int getHeaderSize() {
204    return NUM_BYTES_HEADER;
205  }
206
207  /**
208   * For low level debugging of GC subsystem.
209   * Dump the header word(s) of the given object reference.
210   * @param ref the object reference whose header should be dumped
211   */
212  public static void dumpHeader(Object ref) {
213    // by default nothing to do, unless the misc header is required
214    if (GENERATE_GC_TRACE) {
215      VM.sysWrite(" OID=", getOID(ref));
216      VM.sysWrite(" LINK=", getLink(ref));
217      VM.sysWrite(" DEATH=", getDeathTime(ref));
218    }
219  }
220}