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