summaryrefslogtreecommitdiffstats
path: root/runtime/lock_word.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lock_word.h')
-rw-r--r--runtime/lock_word.h129
1 files changed, 102 insertions, 27 deletions
diff --git a/runtime/lock_word.h b/runtime/lock_word.h
index 2d5c71bb93..46c3bd4a99 100644
--- a/runtime/lock_word.h
+++ b/runtime/lock_word.h
@@ -21,6 +21,7 @@
#include <stdint.h>
#include "base/logging.h"
+#include "read_barrier.h"
#include "utils.h"
namespace art {
@@ -31,34 +32,43 @@ namespace mirror {
class Monitor;
/* The lock value itself as stored in mirror::Object::monitor_. The two most significant bits of
- * the state. The three possible states are fat locked, thin/unlocked, and hash code.
- * When the lock word is in the "thin" state and its bits are formatted as follows:
+ * the state. The four possible states are fat locked, thin/unlocked, hash code, and forwarding
+ * address. When the lock word is in the "thin" state and its bits are formatted as follows:
*
- * |33|22222222221111|1111110000000000|
- * |10|98765432109876|5432109876543210|
- * |00| lock count |thread id owner |
+ * |33|22|222222221111|1111110000000000|
+ * |10|98|765432109876|5432109876543210|
+ * |00|rb| lock count |thread id owner |
*
* When the lock word is in the "fat" state and its bits are formatted as follows:
*
- * |33|222222222211111111110000000000|
- * |10|987654321098765432109876543210|
- * |01| MonitorId |
+ * |33|22|2222222211111111110000000000|
+ * |10|98|7654321098765432109876543210|
+ * |01|rb| MonitorId |
*
* When the lock word is in hash state and its bits are formatted as follows:
*
- * |33|222222222211111111110000000000|
- * |10|987654321098765432109876543210|
- * |10| HashCode |
+ * |33|22|2222222211111111110000000000|
+ * |10|98|7654321098765432109876543210|
+ * |10|rb| HashCode |
+ *
+ * When the lock word is in fowarding address state and its bits are formatted as follows:
+ *
+ * |33|22|2222222211111111110000000000|
+ * |10|98|7654321098765432109876543210|
+ * |11| ForwardingAddress |
+ *
+ * The rb bits store the read barrier state.
*/
class LockWord {
public:
enum SizeShiftsAndMasks { // private marker to avoid generate-operator-out.py from processing.
// Number of bits to encode the state, currently just fat or thin/unlocked or hash code.
kStateSize = 2,
+ kReadBarrierStateSize = 2,
// Number of bits to encode the thin lock owner.
kThinLockOwnerSize = 16,
// Remaining bits are the recursive lock count.
- kThinLockCountSize = 32 - kThinLockOwnerSize - kStateSize,
+ kThinLockCountSize = 32 - kThinLockOwnerSize - kStateSize - kReadBarrierStateSize,
// Thin lock bits. Owner in lowest bits.
kThinLockOwnerShift = 0,
@@ -68,28 +78,41 @@ class LockWord {
kThinLockCountShift = kThinLockOwnerSize + kThinLockOwnerShift,
kThinLockCountMask = (1 << kThinLockCountSize) - 1,
kThinLockMaxCount = kThinLockCountMask,
+ kThinLockCountOne = 1 << kThinLockCountShift, // == 65536 (0x10000)
// State in the highest bits.
- kStateShift = kThinLockCountSize + kThinLockCountShift,
+ kStateShift = kReadBarrierStateSize + kThinLockCountSize + kThinLockCountShift,
kStateMask = (1 << kStateSize) - 1,
+ kStateMaskShifted = kStateMask << kStateShift,
kStateThinOrUnlocked = 0,
kStateFat = 1,
kStateHash = 2,
kStateForwardingAddress = 3,
+ kReadBarrierStateShift = kThinLockCountSize + kThinLockCountShift,
+ kReadBarrierStateMask = (1 << kReadBarrierStateSize) - 1,
+ kReadBarrierStateMaskShifted = kReadBarrierStateMask << kReadBarrierStateShift,
+ kReadBarrierStateMaskShiftedToggled = ~kReadBarrierStateMaskShifted,
// When the state is kHashCode, the non-state bits hold the hashcode.
kHashShift = 0,
- kHashSize = 32 - kStateSize,
+ kHashSize = 32 - kStateSize - kReadBarrierStateSize,
kHashMask = (1 << kHashSize) - 1,
kMaxHash = kHashMask,
+
+ kMonitorIdShift = kHashShift,
+ kMonitorIdSize = kHashSize,
+ kMonitorIdMask = kHashMask,
+ kMonitorIdAlignmentShift = 32 - kMonitorIdSize,
+ kMonitorIdAlignment = 1 << kMonitorIdAlignmentShift,
kMaxMonitorId = kMaxHash
};
- static LockWord FromThinLockId(uint32_t thread_id, uint32_t count) {
+ static LockWord FromThinLockId(uint32_t thread_id, uint32_t count, uint32_t rb_state) {
CHECK_LE(thread_id, static_cast<uint32_t>(kThinLockMaxOwner));
CHECK_LE(count, static_cast<uint32_t>(kThinLockMaxCount));
return LockWord((thread_id << kThinLockOwnerShift) | (count << kThinLockCountShift) |
- (kStateThinOrUnlocked << kStateShift));
+ (rb_state << kReadBarrierStateShift) |
+ (kStateThinOrUnlocked << kStateShift));
}
static LockWord FromForwardingAddress(size_t target) {
@@ -97,9 +120,23 @@ class LockWord {
return LockWord((target >> kStateSize) | (kStateForwardingAddress << kStateShift));
}
- static LockWord FromHashCode(uint32_t hash_code) {
+ static LockWord FromHashCode(uint32_t hash_code, uint32_t rb_state) {
CHECK_LE(hash_code, static_cast<uint32_t>(kMaxHash));
- return LockWord((hash_code << kHashShift) | (kStateHash << kStateShift));
+ return LockWord((hash_code << kHashShift) |
+ (rb_state << kReadBarrierStateShift) |
+ (kStateHash << kStateShift));
+ }
+
+ static LockWord FromDefault(uint32_t rb_state) {
+ return LockWord(rb_state << kReadBarrierStateShift);
+ }
+
+ static bool IsDefault(LockWord lw) {
+ return LockWord().GetValue() == lw.GetValue();
+ }
+
+ static LockWord Default() {
+ return LockWord();
}
enum LockState {
@@ -111,6 +148,7 @@ class LockWord {
};
LockState GetState() const {
+ CheckReadBarrierState();
if (UNLIKELY(value_ == 0)) {
return kUnlocked;
} else {
@@ -129,6 +167,10 @@ class LockWord {
}
}
+ uint32_t ReadBarrierState() const {
+ return (value_ >> kReadBarrierStateShift) & kReadBarrierStateMask;
+ }
+
// Return the owner thin lock thread id.
uint32_t ThinLockOwner() const;
@@ -141,25 +183,58 @@ class LockWord {
// Return the forwarding address stored in the monitor.
size_t ForwardingAddress() const;
+ // Constructor a lock word for inflation to use a Monitor.
+ explicit LockWord(Monitor* mon, uint32_t rb_state);
+
+ // Return the hash code stored in the lock word, must be kHashCode state.
+ int32_t GetHashCode() const;
+
+ template <bool kIncludeReadBarrierState>
+ static bool Equal(LockWord lw1, LockWord lw2) {
+ if (kIncludeReadBarrierState) {
+ return lw1.GetValue() == lw2.GetValue();
+ }
+ return lw1.GetValueWithoutReadBarrierState() == lw2.GetValueWithoutReadBarrierState();
+ }
+
+ private:
// Default constructor with no lock ownership.
LockWord();
- // Constructor a lock word for inflation to use a Monitor.
- explicit LockWord(Monitor* mon);
-
- bool operator==(const LockWord& rhs) const {
- return GetValue() == rhs.GetValue();
+ explicit LockWord(uint32_t val) : value_(val) {
+ CheckReadBarrierState();
}
- // Return the hash code stored in the lock word, must be kHashCode state.
- int32_t GetHashCode() const;
+ // Disallow this in favor of explicit Equal() with the
+ // kIncludeReadBarrierState param to make clients be aware of the
+ // read barrier state.
+ bool operator==(const LockWord& rhs) = delete;
+
+ void CheckReadBarrierState() const {
+ if (kIsDebugBuild && ((value_ >> kStateShift) & kStateMask) != kStateForwardingAddress) {
+ uint32_t rb_state = ReadBarrierState();
+ if (!kUseReadBarrier) {
+ DCHECK_EQ(rb_state, 0U);
+ } else {
+ DCHECK(rb_state == ReadBarrier::white_ptr_ ||
+ rb_state == ReadBarrier::gray_ptr_ ||
+ rb_state == ReadBarrier::black_ptr_) << rb_state;
+ }
+ }
+ }
+ // Note GetValue() includes the read barrier bits and comparing (==)
+ // GetValue() between two lock words to compare the lock states may
+ // not work. Prefer Equal() or GetValueWithoutReadBarrierState().
uint32_t GetValue() const {
+ CheckReadBarrierState();
return value_;
}
- private:
- explicit LockWord(uint32_t val) : value_(val) {}
+ uint32_t GetValueWithoutReadBarrierState() const {
+ CheckReadBarrierState();
+ return value_ & ~(kReadBarrierStateMask << kReadBarrierStateShift);
+ }
// Only Object should be converting LockWords to/from uints.
friend class mirror::Object;