1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_LOCK_WORD_H_ 18 #define ART_RUNTIME_LOCK_WORD_H_ 19 20 #include <cstdint> 21 #include <iosfwd> 22 23 #include <android-base/logging.h> 24 25 #include "base/bit_utils.h" 26 #include "read_barrier.h" 27 28 namespace art { 29 namespace mirror { 30 class Object; 31 } // namespace mirror 32 33 class Monitor; 34 35 /* The lock value itself as stored in mirror::Object::monitor_. The two most significant bits of 36 * the state. The four possible states are fat locked, thin/unlocked, hash code, and forwarding 37 * address. 38 * 39 * When the lock word is in the "thin" state and its bits are formatted as follows: 40 * 41 * |33|2|2|222222221111|1111110000000000| 42 * |10|9|8|765432109876|5432109876543210| 43 * |00|m|r| lock count |thread id owner | 44 * 45 * When the lock word is in the "fat" state and its bits are formatted as follows: 46 * 47 * |33|2|2|2222222211111111110000000000| 48 * |10|9|8|7654321098765432109876543210| 49 * |01|m|r| MonitorId | 50 * 51 * When the lock word is in hash state and its bits are formatted as follows: 52 * 53 * |33|2|2|2222222211111111110000000000| 54 * |10|9|8|7654321098765432109876543210| 55 * |10|m|r| HashCode | 56 * 57 * When the lock word is in forwarding address state and its bits are formatted as follows: 58 * 59 * |33|2|22222222211111111110000000000| 60 * |10|9|87654321098765432109876543210| 61 * |11|0| ForwardingAddress | 62 * 63 * The `r` bit stores the read barrier state. 64 * The `m` bit stores the mark bit state. 65 */ 66 class LockWord { 67 public: 68 enum SizeShiftsAndMasks : uint32_t { // private marker to avoid generate-operator-out.py from processing. 69 // Number of bits to encode the state, currently just fat or thin/unlocked or hash code. 70 kStateSize = 2, 71 kReadBarrierStateSize = 1, 72 kMarkBitStateSize = 1, 73 // Number of bits to encode the thin lock owner. 74 kThinLockOwnerSize = 16, 75 // Remaining bits are the recursive lock count. 76 kThinLockCountSize = 32 - kThinLockOwnerSize - kStateSize - kReadBarrierStateSize - 77 kMarkBitStateSize, 78 // Thin lock bits. Owner in lowest bits. 79 80 kThinLockOwnerShift = 0, 81 kThinLockOwnerMask = (1 << kThinLockOwnerSize) - 1, 82 kThinLockMaxOwner = kThinLockOwnerMask, 83 // Count in higher bits. 84 kThinLockCountShift = kThinLockOwnerSize + kThinLockOwnerShift, 85 kThinLockCountMask = (1 << kThinLockCountSize) - 1, 86 kThinLockMaxCount = kThinLockCountMask, 87 kThinLockCountOne = 1 << kThinLockCountShift, // == 65536 (0x10000) 88 89 // State in the highest bits. 90 kStateShift = kReadBarrierStateSize + kThinLockCountSize + kThinLockCountShift + 91 kMarkBitStateSize, 92 kStateMask = (1 << kStateSize) - 1, 93 kStateMaskShifted = kStateMask << kStateShift, 94 kStateThinOrUnlocked = 0, 95 kStateFat = 1, 96 kStateHash = 2, 97 kStateForwardingAddress = 3, 98 kStateForwardingAddressShifted = kStateForwardingAddress << kStateShift, 99 kStateForwardingAddressOverflow = (1 + kStateMask - kStateForwardingAddress) << kStateShift, 100 101 // Read barrier bit. 102 kReadBarrierStateShift = kThinLockCountSize + kThinLockCountShift, 103 kReadBarrierStateMask = (1 << kReadBarrierStateSize) - 1, 104 kReadBarrierStateMaskShifted = kReadBarrierStateMask << kReadBarrierStateShift, 105 kReadBarrierStateMaskShiftedToggled = ~kReadBarrierStateMaskShifted, 106 107 // Mark bit. 108 kMarkBitStateShift = kReadBarrierStateSize + kReadBarrierStateShift, 109 kMarkBitStateMask = (1 << kMarkBitStateSize) - 1, 110 kMarkBitStateMaskShifted = kMarkBitStateMask << kMarkBitStateShift, 111 kMarkBitStateMaskShiftedToggled = ~kMarkBitStateMaskShifted, 112 113 // GC state is mark bit and read barrier state. 114 kGCStateSize = kReadBarrierStateSize + kMarkBitStateSize, 115 kGCStateShift = kReadBarrierStateShift, 116 kGCStateMaskShifted = kReadBarrierStateMaskShifted | kMarkBitStateMaskShifted, 117 kGCStateMaskShiftedToggled = ~kGCStateMaskShifted, 118 119 // When the state is kHashCode, the non-state bits hold the hashcode. 120 // Note Object.hashCode() has the hash code layout hardcoded. 121 kHashShift = 0, 122 kHashSize = 32 - kStateSize - kReadBarrierStateSize - kMarkBitStateSize, 123 kHashMask = (1 << kHashSize) - 1, 124 kMaxHash = kHashMask, 125 126 // Forwarding address shift. 127 kForwardingAddressShift = kObjectAlignmentShift, 128 129 kMonitorIdShift = kHashShift, 130 kMonitorIdSize = kHashSize, 131 kMonitorIdMask = kHashMask, 132 kMonitorIdAlignmentShift = 32 - kMonitorIdSize, 133 kMonitorIdAlignment = 1 << kMonitorIdAlignmentShift, 134 kMaxMonitorId = kMaxHash 135 }; 136 FromThinLockId(uint32_t thread_id,uint32_t count,uint32_t gc_state)137 static LockWord FromThinLockId(uint32_t thread_id, uint32_t count, uint32_t gc_state) { 138 CHECK_LE(thread_id, static_cast<uint32_t>(kThinLockMaxOwner)); 139 CHECK_LE(count, static_cast<uint32_t>(kThinLockMaxCount)); 140 // DCHECK_EQ(gc_bits & kGCStateMaskToggled, 0U); 141 return LockWord((thread_id << kThinLockOwnerShift) | 142 (count << kThinLockCountShift) | 143 (gc_state << kGCStateShift) | 144 (kStateThinOrUnlocked << kStateShift)); 145 } 146 FromForwardingAddress(size_t target)147 static LockWord FromForwardingAddress(size_t target) { 148 DCHECK_ALIGNED(target, (1 << kStateSize)); 149 return LockWord((target >> kForwardingAddressShift) | kStateForwardingAddressShifted); 150 } 151 FromHashCode(uint32_t hash_code,uint32_t gc_state)152 static LockWord FromHashCode(uint32_t hash_code, uint32_t gc_state) { 153 CHECK_LE(hash_code, static_cast<uint32_t>(kMaxHash)); 154 // DCHECK_EQ(gc_bits & kGCStateMaskToggled, 0U); 155 return LockWord((hash_code << kHashShift) | 156 (gc_state << kGCStateShift) | 157 (kStateHash << kStateShift)); 158 } 159 FromDefault(uint32_t gc_state)160 static LockWord FromDefault(uint32_t gc_state) { 161 return LockWord(gc_state << kGCStateShift); 162 } 163 IsDefault(LockWord lw)164 static bool IsDefault(LockWord lw) { 165 return LockWord().GetValue() == lw.GetValue(); 166 } 167 Default()168 static LockWord Default() { 169 return LockWord(); 170 } 171 172 enum LockState { 173 kUnlocked, // No lock owners. 174 kThinLocked, // Single uncontended owner. 175 kFatLocked, // See associated monitor. 176 kHashCode, // Lock word contains an identity hash. 177 kForwardingAddress, // Lock word contains the forwarding address of an object. 178 }; 179 GetState()180 LockState GetState() const { 181 CheckReadBarrierState(); 182 if ((!kUseReadBarrier && UNLIKELY(value_ == 0)) || 183 (kUseReadBarrier && UNLIKELY((value_ & kGCStateMaskShiftedToggled) == 0))) { 184 return kUnlocked; 185 } else { 186 uint32_t internal_state = (value_ >> kStateShift) & kStateMask; 187 switch (internal_state) { 188 case kStateThinOrUnlocked: 189 return kThinLocked; 190 case kStateHash: 191 return kHashCode; 192 case kStateForwardingAddress: 193 return kForwardingAddress; 194 default: 195 DCHECK_EQ(internal_state, static_cast<uint32_t>(kStateFat)); 196 return kFatLocked; 197 } 198 } 199 } 200 ReadBarrierState()201 uint32_t ReadBarrierState() const { 202 return (value_ >> kReadBarrierStateShift) & kReadBarrierStateMask; 203 } 204 GCState()205 uint32_t GCState() const { 206 return (value_ & kGCStateMaskShifted) >> kGCStateShift; 207 } 208 SetReadBarrierState(uint32_t rb_state)209 void SetReadBarrierState(uint32_t rb_state) { 210 DCHECK_EQ(rb_state & ~kReadBarrierStateMask, 0U); 211 DCHECK(rb_state == ReadBarrier::WhiteState() || 212 rb_state == ReadBarrier::GrayState()) << rb_state; 213 DCHECK_NE(static_cast<uint32_t>(GetState()), static_cast<uint32_t>(kForwardingAddress)); 214 // Clear and or the bits. 215 value_ &= ~(kReadBarrierStateMask << kReadBarrierStateShift); 216 value_ |= (rb_state & kReadBarrierStateMask) << kReadBarrierStateShift; 217 } 218 219 MarkBitState()220 uint32_t MarkBitState() const { 221 return (value_ >> kMarkBitStateShift) & kMarkBitStateMask; 222 } 223 SetMarkBitState(uint32_t mark_bit)224 void SetMarkBitState(uint32_t mark_bit) { 225 DCHECK_EQ(mark_bit & ~kMarkBitStateMask, 0U); 226 DCHECK_NE(static_cast<uint32_t>(GetState()), static_cast<uint32_t>(kForwardingAddress)); 227 // Clear and or the bits. 228 value_ &= kMarkBitStateMaskShiftedToggled; 229 value_ |= mark_bit << kMarkBitStateShift; 230 } 231 232 // Return the owner thin lock thread id. 233 uint32_t ThinLockOwner() const; 234 235 // Return the number of times a lock value has been locked. 236 uint32_t ThinLockCount() const; 237 238 // Return the Monitor encoded in a fat lock. 239 Monitor* FatLockMonitor() const; 240 241 // Return the forwarding address stored in the monitor. 242 size_t ForwardingAddress() const; 243 244 // Constructor a lock word for inflation to use a Monitor. 245 LockWord(Monitor* mon, uint32_t gc_state); 246 247 // Return the hash code stored in the lock word, must be kHashCode state. 248 int32_t GetHashCode() const; 249 250 template <bool kIncludeReadBarrierState> Equal(LockWord lw1,LockWord lw2)251 static bool Equal(LockWord lw1, LockWord lw2) { 252 if (kIncludeReadBarrierState) { 253 return lw1.GetValue() == lw2.GetValue(); 254 } 255 return lw1.GetValueWithoutGCState() == lw2.GetValueWithoutGCState(); 256 } 257 Dump(std::ostream & os)258 void Dump(std::ostream& os) { 259 os << "LockWord:" << std::hex << value_; 260 } 261 262 private: 263 // Default constructor with no lock ownership. 264 LockWord(); 265 LockWord(uint32_t val)266 explicit LockWord(uint32_t val) : value_(val) { 267 // Make sure adding the overflow causes an overflow. 268 constexpr uint64_t overflow = static_cast<uint64_t>(kStateForwardingAddressShifted) + 269 static_cast<uint64_t>(kStateForwardingAddressOverflow); 270 constexpr bool is_larger = overflow > static_cast<uint64_t>(0xFFFFFFFF); 271 static_assert(is_larger, "should have overflowed"); 272 static_assert( 273 (~kStateForwardingAddress & kStateMask) == 0, 274 "READ_BARRIER_MARK_REG relies on the forwarding address state being only one bits"); 275 CheckReadBarrierState(); 276 } 277 278 // Disallow this in favor of explicit Equal() with the 279 // kIncludeReadBarrierState param to make clients be aware of the 280 // read barrier state. 281 bool operator==(const LockWord& rhs) = delete; 282 CheckReadBarrierState()283 void CheckReadBarrierState() const { 284 if (kIsDebugBuild && ((value_ >> kStateShift) & kStateMask) != kStateForwardingAddress) { 285 uint32_t rb_state = ReadBarrierState(); 286 if (!kUseReadBarrier) { 287 DCHECK_EQ(rb_state, 0U); 288 } else { 289 DCHECK(rb_state == ReadBarrier::WhiteState() || 290 rb_state == ReadBarrier::GrayState()) << rb_state; 291 } 292 } 293 } 294 295 // Note GetValue() includes the read barrier bits and comparing (==) 296 // GetValue() between two lock words to compare the lock states may 297 // not work. Prefer Equal() or GetValueWithoutReadBarrierState(). GetValue()298 uint32_t GetValue() const { 299 CheckReadBarrierState(); 300 return value_; 301 } 302 GetValueWithoutGCState()303 uint32_t GetValueWithoutGCState() const { 304 CheckReadBarrierState(); 305 return value_ & kGCStateMaskShiftedToggled; 306 } 307 308 // Only Object should be converting LockWords to/from uints. 309 friend class mirror::Object; 310 311 // The encoded value holding all the state. 312 uint32_t value_; 313 }; 314 std::ostream& operator<<(std::ostream& os, const LockWord::LockState& code); 315 316 } // namespace art 317 318 319 #endif // ART_RUNTIME_LOCK_WORD_H_ 320