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