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 }