1 /* 2 * Copyright (c) 2001, 2020, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * 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 import sun.jvm.hotspot.utilities.Observable; 35 import sun.jvm.hotspot.utilities.Observer; 36 37 public class Mark extends VMObject { 38 static { 39 VM.registerVMInitializedObserver(new Observer() { 40 public void update(Observable o, Object data) { 41 initialize(VM.getVM().getTypeDataBase()); 42 } 43 }); 44 } 45 46 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { 47 Type type = db.lookupType("oopDesc"); 48 markField = type.getCIntegerField("_mark"); 49 50 ageBits = db.lookupLongConstant("markWord::age_bits").longValue(); 51 lockBits = db.lookupLongConstant("markWord::lock_bits").longValue(); 52 biasedLockBits = db.lookupLongConstant("markWord::biased_lock_bits").longValue(); 53 maxHashBits = db.lookupLongConstant("markWord::max_hash_bits").longValue(); 54 hashBits = db.lookupLongConstant("markWord::hash_bits").longValue(); 55 hashBitsCompact = db.lookupLongConstant("markWord::hash_bits_compact").longValue(); 56 lockShift = db.lookupLongConstant("markWord::lock_shift").longValue(); 57 biasedLockShift = db.lookupLongConstant("markWord::biased_lock_shift").longValue(); 58 ageShift = db.lookupLongConstant("markWord::age_shift").longValue(); 59 hashShift = db.lookupLongConstant("markWord::hash_shift").longValue(); 60 hashShiftCompact = db.lookupLongConstant("markWord::hash_shift_compact").longValue(); 61 if (VM.getVM().isLP64()) { 62 klassShift = db.lookupLongConstant("markWord::klass_shift").longValue(); 63 } 64 lockMask = db.lookupLongConstant("markWord::lock_mask").longValue(); 65 lockMaskInPlace = db.lookupLongConstant("markWord::lock_mask_in_place").longValue(); 66 biasedLockMask = db.lookupLongConstant("markWord::biased_lock_mask").longValue(); 67 biasedLockMaskInPlace = db.lookupLongConstant("markWord::biased_lock_mask_in_place").longValue(); 68 biasedLockBitInPlace = db.lookupLongConstant("markWord::biased_lock_bit_in_place").longValue(); 69 ageMask = db.lookupLongConstant("markWord::age_mask").longValue(); 70 ageMaskInPlace = db.lookupLongConstant("markWord::age_mask_in_place").longValue(); 71 hashMask = db.lookupLongConstant("markWord::hash_mask").longValue(); 72 hashMaskInPlace = db.lookupLongConstant("markWord::hash_mask_in_place").longValue(); 73 hashMaskCompact = db.lookupLongConstant("markWord::hash_mask_compact").longValue(); 74 hashMaskCompactInPlace = db.lookupLongConstant("markWord::hash_mask_compact_in_place").longValue(); 75 biasedLockAlignment = db.lookupLongConstant("markWord::biased_lock_alignment").longValue(); 76 lockedValue = db.lookupLongConstant("markWord::locked_value").longValue(); 77 unlockedValue = db.lookupLongConstant("markWord::unlocked_value").longValue(); 78 monitorValue = db.lookupLongConstant("markWord::monitor_value").longValue(); 79 markedValue = db.lookupLongConstant("markWord::marked_value").longValue(); 80 biasedLockPattern = db.lookupLongConstant("markWord::biased_lock_pattern").longValue(); 81 noHash = db.lookupLongConstant("markWord::no_hash").longValue(); 82 noHashInPlace = db.lookupLongConstant("markWord::no_hash_in_place").longValue(); 83 noLockInPlace = db.lookupLongConstant("markWord::no_lock_in_place").longValue(); 84 maxAge = db.lookupLongConstant("markWord::max_age").longValue(); 85 } 86 87 // Field accessors 88 private static CIntegerField markField; 89 90 // Constants -- read from VM 91 private static long ageBits; 92 private static long lockBits; 93 private static long biasedLockBits; 94 private static long maxHashBits; 95 private static long hashBits; 96 private static long hashBitsCompact; 97 98 private static long lockShift; 99 private static long biasedLockShift; 100 private static long ageShift; 101 private static long hashShift; 102 private static long hashShiftCompact; 103 private static long klassShift; 104 105 private static long lockMask; 106 private static long lockMaskInPlace; 107 private static long biasedLockMask; 108 private static long biasedLockMaskInPlace; 109 private static long biasedLockBitInPlace; 110 private static long ageMask; 111 private static long ageMaskInPlace; 112 private static long hashMask; 113 private static long hashMaskInPlace; 114 private static long hashMaskCompact; 115 private static long hashMaskCompactInPlace; 116 private static long biasedLockAlignment; 117 118 private static long lockedValue; 119 private static long unlockedValue; 120 private static long monitorValue; 121 private static long markedValue; 122 private static long biasedLockPattern; 123 124 private static long noHash; 125 126 private static long noHashInPlace; 127 private static long noLockInPlace; 128 129 private static long maxAge; 130 131 /* Constants in markWord used by CMS. */ 132 private static long cmsShift; 133 private static long cmsMask; 134 private static long sizeShift; 135 136 public static long getKlassShift() { 137 return klassShift; 138 } 139 140 public Mark(Address addr) { 141 super(addr); 142 } 143 144 public long value() { 145 return markField.getValue(addr); 146 } 147 148 public Address valueAsAddress() { 149 return addr.getAddressAt(markField.getOffset()); 150 } 151 152 // Biased locking accessors 153 // These must be checked by all code which calls into the 154 // ObjectSynchoronizer and other code. The biasing is not understood 155 // by the lower-level CAS-based locking code, although the runtime 156 // fixes up biased locks to be compatible with it when a bias is 157 // revoked. 158 public boolean hasBiasPattern() { 159 return (Bits.maskBitsLong(value(), biasedLockMaskInPlace) == biasedLockPattern); 160 } 161 162 public JavaThread biasedLocker() { 163 Threads threads = VM.getVM().getThreads(); 164 Address addr = valueAsAddress().andWithMask(~(biasedLockMaskInPlace & ageMaskInPlace)); 165 return threads.createJavaThreadWrapper(addr); 166 } 167 168 // Indicates that the mark gas the bias bit set but that it has not 169 // yet been biased toward a particular thread 170 public boolean isBiasedAnonymously() { 171 return hasBiasPattern() && (biasedLocker() == null); 172 } 173 174 // lock accessors (note that these assume lock_shift == 0) 175 public boolean isLocked() { 176 return (Bits.maskBitsLong(value(), lockMaskInPlace) != unlockedValue); 177 } 178 public boolean isUnlocked() { 179 return (Bits.maskBitsLong(value(), biasedLockMaskInPlace) == unlockedValue); 180 } 181 public boolean isMarked() { 182 return (Bits.maskBitsLong(value(), lockMaskInPlace) == markedValue); 183 } 184 185 // Special temporary state of the markWord while being inflated. 186 // Code that looks at mark outside a lock need to take this into account. 187 public boolean isBeingInflated() { 188 return (value() == 0); 189 } 190 191 // Should this header be preserved during GC? 192 public boolean mustBePreserved() { 193 return (!isUnlocked() || !hasNoHash()); 194 } 195 196 // WARNING: The following routines are used EXCLUSIVELY by 197 // synchronization functions. They are not really gc safe. 198 // They must get updated if markWord layout get changed. 199 200 public boolean hasLocker() { 201 return ((value() & lockMaskInPlace) == lockedValue); 202 } 203 public BasicLock locker() { 204 if (Assert.ASSERTS_ENABLED) { 205 Assert.that(hasLocker(), "check"); 206 } 207 return new BasicLock(valueAsAddress()); 208 } 209 public boolean hasMonitor() { 210 return ((value() & monitorValue) != 0); 211 } 212 public ObjectMonitor monitor() { 213 if (Assert.ASSERTS_ENABLED) { 214 Assert.that(hasMonitor(), "check"); 215 } 216 // Use xor instead of &~ to provide one extra tag-bit check. 217 Address monAddr = valueAsAddress().xorWithMask(monitorValue); 218 return new ObjectMonitor(monAddr); 219 } 220 public boolean hasDisplacedMarkHelper() { 221 return ((value() & unlockedValue) == 0); 222 } 223 public Mark displacedMarkHelper() { 224 if (Assert.ASSERTS_ENABLED) { 225 Assert.that(hasDisplacedMarkHelper(), "check"); 226 } 227 Address addr = valueAsAddress().andWithMask(~monitorValue); 228 return new Mark(addr.getAddressAt(0)); 229 } 230 public int age() { return (int) Bits.maskBitsLong(value() >> ageShift, ageMask); } 231 232 // hash operations 233 public long hash() { 234 if (VM.getVM().isCompactObjectHeadersEnabled()) { 235 return Bits.maskBitsLong(value() >> hashShiftCompact, hashMaskCompact); 236 } else { 237 return Bits.maskBitsLong(value() >> hashShift, hashMask); 238 } 239 } 240 241 public boolean hasNoHash() { 242 return hash() == noHash; 243 } 244 245 public Klass getKlass() { 246 assert(VM.getVM().isCompactObjectHeadersEnabled()); 247 assert(!hasMonitor()); 248 return (Klass)Metadata.instantiateWrapperFor(addr.getCompKlassAddressAt(0)); 249 } 250 251 // Debugging 252 public void printOn(PrintStream tty) { 253 if (isLocked()) { 254 tty.print("locked(0x" + 255 Long.toHexString(value()) + ")->"); 256 displacedMarkHelper().printOn(tty); 257 } else { 258 if (Assert.ASSERTS_ENABLED) { 259 Assert.that(isUnlocked(), "just checking"); 260 } 261 tty.print("mark("); 262 tty.print("hash " + Long.toHexString(hash()) + ","); 263 tty.print("age " + age() + ")"); 264 } 265 } 266 267 public long getSize() { return (long)(value() >> sizeShift); } 268 }