1 /* 2 * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.oops; 26 27 import java.io.*; 28 import java.util.*; 29 30 import sun.jvm.hotspot.debugger.*; 31 import sun.jvm.hotspot.runtime.*; 32 import sun.jvm.hotspot.types.*; 33 import sun.jvm.hotspot.utilities.*; 34 35 /** Mark is the analogue of the VM's markOop. In this system it does 36 not subclass Oop but VMObject. For a mark on the stack, the mark's 37 address will be an Address; for a mark in the header of an object, 38 it will be an OopHandle. It is assumed in a couple of places in 39 this code that the mark is the first word in an object. */ 40 41 public class Mark extends VMObject { 42 static { 43 VM.registerVMInitializedObserver(new Observer() { 44 public void update(Observable o, Object data) { 45 initialize(VM.getVM().getTypeDataBase()); 46 } 47 }); 48 } 49 50 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { 51 Type type = db.lookupType("oopDesc"); 52 markField = type.getCIntegerField("_mark"); 53 54 ageBits = db.lookupLongConstant("markOopDesc::age_bits").longValue(); 55 lockBits = db.lookupLongConstant("markOopDesc::lock_bits").longValue(); 56 biasedLockBits = db.lookupLongConstant("markOopDesc::biased_lock_bits").longValue(); 57 maxHashBits = db.lookupLongConstant("markOopDesc::max_hash_bits").longValue(); 58 hashBits = db.lookupLongConstant("markOopDesc::hash_bits").longValue(); 59 lockShift = db.lookupLongConstant("markOopDesc::lock_shift").longValue(); 60 biasedLockShift = db.lookupLongConstant("markOopDesc::biased_lock_shift").longValue(); 61 ageShift = db.lookupLongConstant("markOopDesc::age_shift").longValue(); 62 hashShift = db.lookupLongConstant("markOopDesc::hash_shift").longValue(); 63 lockMask = db.lookupLongConstant("markOopDesc::lock_mask").longValue(); 64 lockMaskInPlace = db.lookupLongConstant("markOopDesc::lock_mask_in_place").longValue(); 65 biasedLockMask = db.lookupLongConstant("markOopDesc::biased_lock_mask").longValue(); 66 biasedLockMaskInPlace = db.lookupLongConstant("markOopDesc::biased_lock_mask_in_place").longValue(); 67 biasedLockBitInPlace = db.lookupLongConstant("markOopDesc::biased_lock_bit_in_place").longValue(); 68 ageMask = db.lookupLongConstant("markOopDesc::age_mask").longValue(); 69 ageMaskInPlace = db.lookupLongConstant("markOopDesc::age_mask_in_place").longValue(); 70 hashMask = db.lookupLongConstant("markOopDesc::hash_mask").longValue(); 71 hashMaskInPlace = db.lookupLongConstant("markOopDesc::hash_mask_in_place").longValue(); 72 biasedLockAlignment = db.lookupLongConstant("markOopDesc::biased_lock_alignment").longValue(); 73 lockedValue = db.lookupLongConstant("markOopDesc::locked_value").longValue(); 74 unlockedValue = db.lookupLongConstant("markOopDesc::unlocked_value").longValue(); 75 monitorValue = db.lookupLongConstant("markOopDesc::monitor_value").longValue(); 76 markedValue = db.lookupLongConstant("markOopDesc::marked_value").longValue(); 77 biasedLockPattern = db.lookupLongConstant("markOopDesc::biased_lock_pattern").longValue(); 78 noHash = db.lookupLongConstant("markOopDesc::no_hash").longValue(); 79 noHashInPlace = db.lookupLongConstant("markOopDesc::no_hash_in_place").longValue(); 80 noLockInPlace = db.lookupLongConstant("markOopDesc::no_lock_in_place").longValue(); 81 maxAge = db.lookupLongConstant("markOopDesc::max_age").longValue(); 82 83 /* Constants in markOop used by CMS. */ 84 cmsShift = db.lookupLongConstant("markOopDesc::cms_shift").longValue(); 85 cmsMask = db.lookupLongConstant("markOopDesc::cms_mask").longValue(); 86 sizeShift = db.lookupLongConstant("markOopDesc::size_shift").longValue(); 87 } 88 89 // Field accessors 90 private static CIntegerField markField; 91 92 // Constants -- read from VM 93 private static long ageBits; 94 private static long lockBits; 95 private static long biasedLockBits; 96 private static long maxHashBits; 97 private static long hashBits; 98 99 private static long lockShift; 100 private static long biasedLockShift; 101 private static long ageShift; 102 private static long hashShift; 103 104 private static long lockMask; 105 private static long lockMaskInPlace; 106 private static long biasedLockMask; 107 private static long biasedLockMaskInPlace; 108 private static long biasedLockBitInPlace; 109 private static long ageMask; 110 private static long ageMaskInPlace; 111 private static long hashMask; 112 private static long hashMaskInPlace; 113 private static long biasedLockAlignment; 114 115 private static long lockedValue; 116 private static long unlockedValue; 117 private static long monitorValue; 118 private static long markedValue; 119 private static long biasedLockPattern; 120 121 private static long noHash; 122 123 private static long noHashInPlace; 124 private static long noLockInPlace; 125 126 private static long maxAge; 127 128 /* Constants in markOop used by CMS. */ 129 private static long cmsShift; 130 private static long cmsMask; 131 private static long sizeShift; 132 133 public Mark(Address addr) { 134 super(addr); 135 } 136 137 public long value() { 138 return markField.getValue(addr); 139 } 140 141 public Address valueAsAddress() { 142 return addr.getAddressAt(markField.getOffset()); 143 } 144 145 // Biased locking accessors 146 // These must be checked by all code which calls into the 147 // ObjectSynchoronizer and other code. The biasing is not understood 148 // by the lower-level CAS-based locking code, although the runtime 149 // fixes up biased locks to be compatible with it when a bias is 150 // revoked. 151 public boolean hasBiasPattern() { 152 return (Bits.maskBitsLong(value(), biasedLockMaskInPlace) == biasedLockPattern); 153 } 154 155 public JavaThread biasedLocker() { 156 Threads threads = VM.getVM().getThreads(); 157 Address addr = valueAsAddress().andWithMask(~(biasedLockMaskInPlace & ageMaskInPlace)); 158 return threads.createJavaThreadWrapper(addr); 159 } 160 161 // Indicates that the mark gas the bias bit set but that it has not 162 // yet been biased toward a particular thread 163 public boolean isBiasedAnonymously() { 164 return hasBiasPattern() && (biasedLocker() == null); 165 } 166 167 // lock accessors (note that these assume lock_shift == 0) 168 public boolean isLocked() { 169 return (Bits.maskBitsLong(value(), lockMaskInPlace) != unlockedValue); 170 } 171 public boolean isUnlocked() { 172 return (Bits.maskBitsLong(value(), biasedLockMaskInPlace) == unlockedValue); 173 } 174 public boolean isMarked() { 175 return (Bits.maskBitsLong(value(), lockMaskInPlace) == markedValue); 176 } 177 178 // Special temporary state of the markOop while being inflated. 179 // Code that looks at mark outside a lock need to take this into account. 180 public boolean isBeingInflated() { 181 return (value() == 0); 182 } 183 184 // Should this header be preserved during GC? 185 public boolean mustBePreserved() { 186 return (!isUnlocked() || !hasNoHash()); 187 } 188 189 // WARNING: The following routines are used EXCLUSIVELY by 190 // synchronization functions. They are not really gc safe. 191 // They must get updated if markOop layout get changed. 192 193 // FIXME 194 // markOop set_unlocked() const { 195 // return markOop(value() | unlocked_value); 196 // } 197 public boolean hasLocker() { 198 return ((value() & lockMaskInPlace) == lockedValue); 199 } 200 public BasicLock locker() { 201 if (Assert.ASSERTS_ENABLED) { 202 Assert.that(hasLocker(), "check"); 203 } 204 return new BasicLock(valueAsAddress()); 205 } 206 public boolean hasMonitor() { 207 return ((value() & monitorValue) != 0); 208 } 209 public ObjectMonitor monitor() { 210 if (Assert.ASSERTS_ENABLED) { 211 Assert.that(hasMonitor(), "check"); 212 } 213 // Use xor instead of &~ to provide one extra tag-bit check. 214 Address monAddr = valueAsAddress().xorWithMask(monitorValue); 215 return new ObjectMonitor(monAddr); 216 } 217 public boolean hasDisplacedMarkHelper() { 218 return ((value() & unlockedValue) == 0); 219 } 220 public Mark displacedMarkHelper() { 221 if (Assert.ASSERTS_ENABLED) { 222 Assert.that(hasDisplacedMarkHelper(), "check"); 223 } 224 Address addr = valueAsAddress().andWithMask(~monitorValue); 225 return new Mark(addr.getAddressAt(0)); 226 } 227 // FIXME 228 // void set_displaced_mark_helper(markOop m) const { 229 // assert(has_displaced_mark_helper(), "check"); 230 // intptr_t ptr = (value() & ~monitor_value); 231 // *(markOop*)ptr = m; 232 // } 233 // markOop copy_set_hash(intptr_t hash) const { 234 // intptr_t tmp = value() & (~hash_mask_in_place); 235 // tmp |= ((hash & hash_mask) << hash_shift); 236 // return (markOop)tmp; 237 // } 238 // it is only used to be stored into BasicLock as the 239 // indicator that the lock is using heavyweight monitor 240 // static markOop unused_mark() { 241 // return (markOop) marked_value; 242 // } 243 // // the following two functions create the markOop to be 244 // // stored into object header, it encodes monitor info 245 // static markOop encode(BasicLock* lock) { 246 // return (markOop) lock; 247 // } 248 // static markOop encode(ObjectMonitor* monitor) { 249 // intptr_t tmp = (intptr_t) monitor; 250 // return (markOop) (tmp | monitor_value); 251 // } 252 // used for alignment-based marking to reuse the busy state to encode pointers 253 // (see markOop_alignment.hpp) 254 // markOop clear_lock_bits() { return markOop(value() & ~lock_mask_in_place); } 255 // 256 // // age operations 257 // markOop set_marked() { return markOop((value() & ~lock_mask_in_place) | marked_value); } 258 // 259 public int age() { return (int) Bits.maskBitsLong(value() >> ageShift, ageMask); } 260 // markOop set_age(int v) const { 261 // assert((v & ~age_mask) == 0, "shouldn't overflow age field"); 262 // return markOop((value() & ~age_mask_in_place) | (((intptr_t)v & age_mask) << age_shift)); 263 // } 264 // markOop incr_age() const { return age() == max_age ? markOop(this) : set_age(age() + 1); } 265 266 // hash operations 267 public long hash() { 268 return Bits.maskBitsLong(value() >> hashShift, hashMask); 269 } 270 271 public boolean hasNoHash() { 272 return hash() == noHash; 273 } 274 275 // FIXME 276 // Prototype mark for initialization 277 // static markOop prototype() { 278 // return markOop( no_hash_in_place | no_lock_in_place ); 279 // } 280 281 // Debugging 282 public void printOn(PrintStream tty) { 283 if (isLocked()) { 284 tty.print("locked(0x" + 285 Long.toHexString(value()) + ")->"); 286 displacedMarkHelper().printOn(tty); 287 } else { 288 if (Assert.ASSERTS_ENABLED) { 289 Assert.that(isUnlocked(), "just checking"); 290 } 291 tty.print("mark("); 292 tty.print("hash " + Long.toHexString(hash()) + ","); 293 tty.print("age " + age() + ")"); 294 } 295 } 296 297 // FIXME 298 // // Prepare address of oop for placement into mark 299 // inline static markOop encode_pointer_as_mark(void* p) { return markOop(p)->set_marked(); } 300 // 301 // // Recover address of oop from encoded form used in mark 302 // inline void* decode_pointer() { return clear_lock_bits(); } 303 304 // Copy markOop methods for CMS here. 305 public boolean isCmsFreeChunk() { 306 return isUnlocked() && 307 (Bits.maskBitsLong(value() >> cmsShift, cmsMask) & 0x1L) == 0x1L; 308 } 309 public long getSize() { return (long)(value() >> sizeShift); } 310 }