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|22|222222221111|1111110000000000| 39 * |10|98|765432109876|5432109876543210| 40 * |00|rb| 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|22|2222222211111111110000000000| 45 * |10|98|7654321098765432109876543210| 46 * |01|rb| MonitorId | 47 * 48 * When the lock word is in hash state and its bits are formatted as follows: 49 * 50 * |33|22|2222222211111111110000000000| 51 * |10|98|7654321098765432109876543210| 52 * |10|rb| HashCode | 53 * 54 * When the lock word is in fowarding address state and its bits are formatted as follows: 55 * 56 * |33|22|2222222211111111110000000000| 57 * |10|98|7654321098765432109876543210| 58 * |11| ForwardingAddress | 59 * 60 * The rb bits store the read barrier state. 61 */ 62 class LockWord { 63 public: 64 enum SizeShiftsAndMasks { // 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 = 2, 68 // Number of bits to encode the thin lock owner. 69 kThinLockOwnerSize = 16, 70 // Remaining bits are the recursive lock count. 71 kThinLockCountSize = 32 - kThinLockOwnerSize - kStateSize - kReadBarrierStateSize, 72 // Thin lock bits. Owner in lowest bits. 73 74 kThinLockOwnerShift = 0, 75 kThinLockOwnerMask = (1 << kThinLockOwnerSize) - 1, 76 kThinLockMaxOwner = kThinLockOwnerMask, 77 // Count in higher bits. 78 kThinLockCountShift = kThinLockOwnerSize + kThinLockOwnerShift, 79 kThinLockCountMask = (1 << kThinLockCountSize) - 1, 80 kThinLockMaxCount = kThinLockCountMask, 81 kThinLockCountOne = 1 << kThinLockCountShift, // == 65536 (0x10000) 82 83 // State in the highest bits. 84 kStateShift = kReadBarrierStateSize + kThinLockCountSize + kThinLockCountShift, 85 kStateMask = (1 << kStateSize) - 1, 86 kStateMaskShifted = kStateMask << kStateShift, 87 kStateThinOrUnlocked = 0, 88 kStateFat = 1, 89 kStateHash = 2, 90 kStateForwardingAddress = 3, 91 kReadBarrierStateShift = kThinLockCountSize + kThinLockCountShift, 92 kReadBarrierStateMask = (1 << kReadBarrierStateSize) - 1, 93 kReadBarrierStateMaskShifted = kReadBarrierStateMask << kReadBarrierStateShift, 94 kReadBarrierStateMaskShiftedToggled = ~kReadBarrierStateMaskShifted, 95 96 // When the state is kHashCode, the non-state bits hold the hashcode. 97 // Note Object.hashCode() has the hash code layout hardcoded. 98 kHashShift = 0, 99 kHashSize = 32 - kStateSize - kReadBarrierStateSize, 100 kHashMask = (1 << kHashSize) - 1, 101 kMaxHash = kHashMask, 102 103 kMonitorIdShift = kHashShift, 104 kMonitorIdSize = kHashSize, 105 kMonitorIdMask = kHashMask, 106 kMonitorIdAlignmentShift = 32 - kMonitorIdSize, 107 kMonitorIdAlignment = 1 << kMonitorIdAlignmentShift, 108 kMaxMonitorId = kMaxHash 109 }; 110 111 static LockWord FromThinLockId(uint32_t thread_id, uint32_t count, uint32_t rb_state) { 112 CHECK_LE(thread_id, static_cast<uint32_t>(kThinLockMaxOwner)); 113 CHECK_LE(count, static_cast<uint32_t>(kThinLockMaxCount)); 114 DCHECK_EQ(rb_state & ~kReadBarrierStateMask, 0U); 115 return LockWord((thread_id << kThinLockOwnerShift) | (count << kThinLockCountShift) | 116 (rb_state << kReadBarrierStateShift) | 117 (kStateThinOrUnlocked << kStateShift)); 118 } 119 120 static LockWord FromForwardingAddress(size_t target) { 121 DCHECK_ALIGNED(target, (1 << kStateSize)); 122 return LockWord((target >> kStateSize) | (kStateForwardingAddress << kStateShift)); 123 } 124 125 static LockWord FromHashCode(uint32_t hash_code, uint32_t rb_state) { 126 CHECK_LE(hash_code, static_cast<uint32_t>(kMaxHash)); 127 DCHECK_EQ(rb_state & ~kReadBarrierStateMask, 0U); 128 return LockWord((hash_code << kHashShift) | 129 (rb_state << kReadBarrierStateShift) | 130 (kStateHash << kStateShift)); 131 } 132 133 static LockWord FromDefault(uint32_t rb_state) { 134 DCHECK_EQ(rb_state & ~kReadBarrierStateMask, 0U); 135 return LockWord(rb_state << kReadBarrierStateShift); 136 } 137 138 static bool IsDefault(LockWord lw) { 139 return LockWord().GetValue() == lw.GetValue(); 140 } 141 142 static LockWord Default() { 143 return LockWord(); 144 } 145 146 enum LockState { 147 kUnlocked, // No lock owners. 148 kThinLocked, // Single uncontended owner. 149 kFatLocked, // See associated monitor. 150 kHashCode, // Lock word contains an identity hash. 151 kForwardingAddress, // Lock word contains the forwarding address of an object. 152 }; 153 154 LockState GetState() const { 155 CheckReadBarrierState(); 156 if ((!kUseReadBarrier && UNLIKELY(value_ == 0)) || 157 (kUseReadBarrier && UNLIKELY((value_ & kReadBarrierStateMaskShiftedToggled) == 0))) { 158 return kUnlocked; 159 } else { 160 uint32_t internal_state = (value_ >> kStateShift) & kStateMask; 161 switch (internal_state) { 162 case kStateThinOrUnlocked: 163 return kThinLocked; 164 case kStateHash: 165 return kHashCode; 166 case kStateForwardingAddress: 167 return kForwardingAddress; 168 default: 169 DCHECK_EQ(internal_state, static_cast<uint32_t>(kStateFat)); 170 return kFatLocked; 171 } 172 } 173 } 174 175 uint32_t ReadBarrierState() const { 176 return (value_ >> kReadBarrierStateShift) & kReadBarrierStateMask; 177 } 178 179 void SetReadBarrierState(uint32_t rb_state) { 180 DCHECK_EQ(rb_state & ~kReadBarrierStateMask, 0U); 181 DCHECK_NE(static_cast<uint32_t>(GetState()), static_cast<uint32_t>(kForwardingAddress)); 182 // Clear and or the bits. 183 value_ &= ~(kReadBarrierStateMask << kReadBarrierStateShift); 184 value_ |= (rb_state & kReadBarrierStateMask) << kReadBarrierStateShift; 185 } 186 187 // Return the owner thin lock thread id. 188 uint32_t ThinLockOwner() const; 189 190 // Return the number of times a lock value has been locked. 191 uint32_t ThinLockCount() const; 192 193 // Return the Monitor encoded in a fat lock. 194 Monitor* FatLockMonitor() const; 195 196 // Return the forwarding address stored in the monitor. 197 size_t ForwardingAddress() const; 198 199 // Constructor a lock word for inflation to use a Monitor. 200 LockWord(Monitor* mon, uint32_t rb_state); 201 202 // Return the hash code stored in the lock word, must be kHashCode state. 203 int32_t GetHashCode() const; 204 205 template <bool kIncludeReadBarrierState> 206 static bool Equal(LockWord lw1, LockWord lw2) { 207 if (kIncludeReadBarrierState) { 208 return lw1.GetValue() == lw2.GetValue(); 209 } 210 return lw1.GetValueWithoutReadBarrierState() == lw2.GetValueWithoutReadBarrierState(); 211 } 212 213 void Dump(std::ostream& os) { 214 os << "LockWord:" << std::hex << value_; 215 } 216 217 private: 218 // Default constructor with no lock ownership. 219 LockWord(); 220 221 explicit LockWord(uint32_t val) : value_(val) { 222 CheckReadBarrierState(); 223 } 224 225 // Disallow this in favor of explicit Equal() with the 226 // kIncludeReadBarrierState param to make clients be aware of the 227 // read barrier state. 228 bool operator==(const LockWord& rhs) = delete; 229 230 void CheckReadBarrierState() const { 231 if (kIsDebugBuild && ((value_ >> kStateShift) & kStateMask) != kStateForwardingAddress) { 232 uint32_t rb_state = ReadBarrierState(); 233 if (!kUseReadBarrier) { 234 DCHECK_EQ(rb_state, 0U); 235 } else { 236 DCHECK(rb_state == ReadBarrier::white_ptr_ || 237 rb_state == ReadBarrier::gray_ptr_ || 238 rb_state == ReadBarrier::black_ptr_) << rb_state; 239 } 240 } 241 } 242 243 // Note GetValue() includes the read barrier bits and comparing (==) 244 // GetValue() between two lock words to compare the lock states may 245 // not work. Prefer Equal() or GetValueWithoutReadBarrierState(). 246 uint32_t GetValue() const { 247 CheckReadBarrierState(); 248 return value_; 249 } 250 251 uint32_t GetValueWithoutReadBarrierState() const { 252 CheckReadBarrierState(); 253 return value_ & ~(kReadBarrierStateMask << kReadBarrierStateShift); 254 } 255 256 // Only Object should be converting LockWords to/from uints. 257 friend class mirror::Object; 258 259 // The encoded value holding all the state. 260 uint32_t value_; 261 }; 262 std::ostream& operator<<(std::ostream& os, const LockWord::LockState& code); 263 264 } // namespace art 265 266 267 #endif // ART_RUNTIME_LOCK_WORD_H_ 268