1d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers/*
2d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers * Copyright (C) 2011 The Android Open Source Project
3d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers *
4d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers * Licensed under the Apache License, Version 2.0 (the "License");
5d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers * you may not use this file except in compliance with the License.
6d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers * You may obtain a copy of the License at
7d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers *
8d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers *      http://www.apache.org/licenses/LICENSE-2.0
9d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers *
10d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers * Unless required by applicable law or agreed to in writing, software
11d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers * distributed under the License is distributed on an "AS IS" BASIS,
12d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers * See the License for the specific language governing permissions and
14d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers * limitations under the License.
15d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers */
16d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
17d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers#ifndef ART_RUNTIME_LOCK_WORD_H_
18d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers#define ART_RUNTIME_LOCK_WORD_H_
19d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
20d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers#include <iosfwd>
21d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers#include <stdint.h>
22d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
23d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers#include "base/logging.h"
24590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier#include "utils.h"
25d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
26d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogersnamespace art {
27d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogersnamespace mirror {
28d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  class Object;
29d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers}  // namespace mirror
30d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
31d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogersclass Monitor;
32d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
33ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier/* The lock value itself as stored in mirror::Object::monitor_.  The two most significant bits of
34ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier * the state. The three possible states are fat locked, thin/unlocked, and hash code.
35ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier * When the lock word is in the "thin" state and its bits are formatted as follows:
36d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers *
37ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier *  |33|22222222221111|1111110000000000|
38ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier *  |10|98765432109876|5432109876543210|
39ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier *  |00| lock count   |thread id owner |
40d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers *
41ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier * When the lock word is in the "fat" state and its bits are formatted as follows:
42d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers *
43ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier *  |33|222222222211111111110000000000|
44ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier *  |10|987654321098765432109876543210|
45ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers *  |01| MonitorId                    |
46ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier *
47ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier * When the lock word is in hash state and its bits are formatted as follows:
48ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier *
49ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier *  |33|222222222211111111110000000000|
50ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier *  |10|987654321098765432109876543210|
51ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier *  |10| HashCode                     |
52d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers */
53d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogersclass LockWord {
54d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers public:
55d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  enum {
56ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    // Number of bits to encode the state, currently just fat or thin/unlocked or hash code.
57ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    kStateSize = 2,
58d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    // Number of bits to encode the thin lock owner.
59d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kThinLockOwnerSize = 16,
60d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    // Remaining bits are the recursive lock count.
61d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kThinLockCountSize = 32 - kThinLockOwnerSize - kStateSize,
62d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    // Thin lock bits. Owner in lowest bits.
63ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier
64d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kThinLockOwnerShift = 0,
65d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kThinLockOwnerMask = (1 << kThinLockOwnerSize) - 1,
66d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    // Count in higher bits.
67d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kThinLockCountShift = kThinLockOwnerSize + kThinLockOwnerShift,
688d82de5d7b04b8f43e7d2bb7ee8a66b0c7e71e1bDmitry Petrochenko    kThinLockCountMask = (1 << kThinLockCountSize) - 1,
69d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kThinLockMaxCount = kThinLockCountMask,
70d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
71d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    // State in the highest bits.
72d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kStateShift = kThinLockCountSize + kThinLockCountShift,
73d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kStateMask = (1 << kStateSize) - 1,
74d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kStateThinOrUnlocked = 0,
75d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kStateFat = 1,
76ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    kStateHash = 2,
77590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    kStateForwardingAddress = 3,
78ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier
79ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    // When the state is kHashCode, the non-state bits hold the hashcode.
80ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    kHashShift = 0,
81ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    kHashSize = 32 - kStateSize,
82ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    kHashMask = (1 << kHashSize) - 1,
83d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  };
84d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
85d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  static LockWord FromThinLockId(uint32_t thread_id, uint32_t count) {
86d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    CHECK_LE(thread_id, static_cast<uint32_t>(kThinLockOwnerMask));
87ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    return LockWord((thread_id << kThinLockOwnerShift) | (count << kThinLockCountShift) |
88ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier                     (kStateThinOrUnlocked << kStateShift));
89ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier  }
90ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier
91590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  static LockWord FromForwardingAddress(size_t target) {
92590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    DCHECK(IsAligned < 1 << kStateSize>(target));
93590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    return LockWord((target >> kStateSize) | (kStateForwardingAddress << kStateShift));
94590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  }
95590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
96ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier  static LockWord FromHashCode(uint32_t hash_code) {
97ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    CHECK_LE(hash_code, static_cast<uint32_t>(kHashMask));
98ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    return LockWord((hash_code << kHashShift) | (kStateHash << kStateShift));
99d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  }
100d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
101d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  enum LockState {
102d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kUnlocked,    // No lock owners.
103d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    kThinLocked,  // Single uncontended owner.
104ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    kFatLocked,   // See associated monitor.
105ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier    kHashCode,    // Lock word contains an identity hash.
106590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    kForwardingAddress,  // Lock word contains the forwarding address of an object.
107d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  };
108d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
109d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  LockState GetState() const {
110590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (UNLIKELY(value_ == 0)) {
111d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers      return kUnlocked;
112d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    } else {
113590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      uint32_t internal_state = (value_ >> kStateShift) & kStateMask;
114590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      switch (internal_state) {
115590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        case kStateThinOrUnlocked:
116590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier          return kThinLocked;
117590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        case kStateHash:
118590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier          return kHashCode;
119590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        case kStateForwardingAddress:
120590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier          return kForwardingAddress;
121590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        default:
122590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier          DCHECK_EQ(internal_state, static_cast<uint32_t>(kStateFat));
123590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier          return kFatLocked;
124590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      }
125d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    }
126d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  }
127d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
128d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  // Return the owner thin lock thread id.
129d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  uint32_t ThinLockOwner() const;
130d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
131d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  // Return the number of times a lock value has been locked.
132d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  uint32_t ThinLockCount() const;
133d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
134d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  // Return the Monitor encoded in a fat lock.
135d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  Monitor* FatLockMonitor() const;
136d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
137590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  // Return the forwarding address stored in the monitor.
138590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  size_t ForwardingAddress() const;
139590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
140d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  // Default constructor with no lock ownership.
141d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  LockWord();
142d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
143d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  // Constructor a lock word for inflation to use a Monitor.
144d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  explicit LockWord(Monitor* mon);
145d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
146ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier  bool operator==(const LockWord& rhs) const {
147d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    return GetValue() == rhs.GetValue();
148d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  }
149d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
150ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier  // Return the hash code stored in the lock word, must be kHashCode state.
1514e6a31eb97f22f4480827474b30b9e64f396eaceMathieu Chartier  int32_t GetHashCode() const;
152d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
153d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  uint32_t GetValue() const {
154d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers    return value_;
155d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  }
156d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
157ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier private:
158ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier  explicit LockWord(uint32_t val) : value_(val) {}
159ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier
160d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  // Only Object should be converting LockWords to/from uints.
161d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  friend class mirror::Object;
162d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
163d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  // The encoded value holding all the state.
164d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers  uint32_t value_;
165d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers};
166d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogersstd::ostream& operator<<(std::ostream& os, const LockWord::LockState& code);
167d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
168d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers}  // namespace art
169d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
170d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers
171d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers#endif  // ART_RUNTIME_LOCK_WORD_H_
172