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