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