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}