xref: /aosp_15_r20/art/runtime/monitor_inflation.md (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard WorkerMonitor inflation and the monitor pool
2*795d594fSAndroid Build Coastguard Worker--------------------------------------
3*795d594fSAndroid Build Coastguard Worker
4*795d594fSAndroid Build Coastguard WorkerEvery Java object conceptually has an associated monitor that is used to implement `synchronized`
5*795d594fSAndroid Build Coastguard Workerblocks as well as `Object.wait()` and related functionality. Initially, the state of this monitor
6*795d594fSAndroid Build Coastguard Workeris represented by the 32-bit `LockWord` in every object. This same word is also used to represent
7*795d594fSAndroid Build Coastguard Workerthe system hash code if one has been computed for the object. See `lock_word.h` for details.
8*795d594fSAndroid Build Coastguard Worker
9*795d594fSAndroid Build Coastguard WorkerThe `LockWord` suffices for representing the state of unlocked objects with no waiters, whether or
10*795d594fSAndroid Build Coastguard Workernot they have a system hash code. It can also represent a locked (via a `synchronized` block)
11*795d594fSAndroid Build Coastguard Workerobject that has neither a system hash code, nor an `Object.wait()` waiter. In all other cases, the
12*795d594fSAndroid Build Coastguard Workerlock must be "inflated". In that case, the `LockWord` contents reflect the "fat lock" state, and
13*795d594fSAndroid Build Coastguard Workerit contains primarily a `MonitorId`. We also inflate significantly contended locks, since the lock
14*795d594fSAndroid Build Coastguard Workerword itself does not have space for a wait queue or the like.
15*795d594fSAndroid Build Coastguard Worker
16*795d594fSAndroid Build Coastguard Worker(With the Concurrent Copying garbage collector, the `LockWord` supports another "forwarding
17*795d594fSAndroid Build Coastguard Workeraddress" state. In that case the above information is instead contained in the `LockWord` for the
18*795d594fSAndroid Build Coastguard Workerto-space objects referenced by the forwarding address.)
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard WorkerMonitorIds
21*795d594fSAndroid Build Coastguard Worker----------
22*795d594fSAndroid Build Coastguard WorkerA `MonitorId` is logically a pointer to a `Monitor` structure. The `Monitor` data structure is
23*795d594fSAndroid Build Coastguard Workerallocated when needed, and holds all the data needed to support any hashcode or `Object`
24*795d594fSAndroid Build Coastguard Workersynchronization operation provided by Java. On 32-bit implementations, it is essentially a
25*795d594fSAndroid Build Coastguard Workerpointer, except for some shifting and masking to avoid collisions with a few bits in the lock word
26*795d594fSAndroid Build Coastguard Workerrequired for other purposes. In a 64-bit environment, the situation is more complicated, since we
27*795d594fSAndroid Build Coastguard Workerdon't have enough bits in the lock word to store a 64-bit pointer.
28*795d594fSAndroid Build Coastguard Worker
29*795d594fSAndroid Build Coastguard WorkerIn the 64-bit case, `Monitor`s are stored in "chunks" of 4K bytes. The bottom bits of a
30*795d594fSAndroid Build Coastguard Worker`MonitorId` are the index of the `Monitor` within its chunk. The remaining bits are used to find
31*795d594fSAndroid Build Coastguard Workerthe correct chunk.
32*795d594fSAndroid Build Coastguard Worker
33*795d594fSAndroid Build Coastguard WorkerContinuing with the 64-bit case, chunk addresses are stored in the `monitor_chunks_` data
34*795d594fSAndroid Build Coastguard Workerstructure, which is logically a two-dimensional, vaguely triangular, array of pointers to chunks
35*795d594fSAndroid Build Coastguard WorkerEach row is allocated separately, and twice as long as the previous one. (Thus the array is not
36*795d594fSAndroid Build Coastguard Workerreally triangular.) The high bits of a `MonitorId` are interpreted as row- and column-indices into
37*795d594fSAndroid Build Coastguard Workerthis array. Both the second level "rows" of this array, and the chunks themselves are allocated on
38*795d594fSAndroid Build Coastguard Workerdemand.  By making the rows grow exponentially in size, and keeping a free list of recycled
39*795d594fSAndroid Build Coastguard Worker`Monitor` slots, we can accommodate a large number of `Monitor`s, without ever allocating more than
40*795d594fSAndroid Build Coastguard Workertwice the index size that was actually required.  (This doesn't count the top-level index needed
41*795d594fSAndroid Build Coastguard Workerto find the rows, but exponential growth of the rows makes that tiny.) And there is no need to
42*795d594fSAndroid Build Coastguard Workerever move `Monitor` objects, which would significantly complicate the logic.
43*795d594fSAndroid Build Coastguard Worker
44*795d594fSAndroid Build Coastguard WorkerThe above data structure is distinct from the `MonitorList` data structure, which is used simply
45*795d594fSAndroid Build Coastguard Workerto enumerate all monitors. (It might be possible to save a bit of space in the 64-bit case, and
46*795d594fSAndroid Build Coastguard Workerhave the `monitor_chunks_` data structure handle this as well.)
47*795d594fSAndroid Build Coastguard Worker
48*795d594fSAndroid Build Coastguard WorkerMonitor inflation
49*795d594fSAndroid Build Coastguard Worker-----------------
50*795d594fSAndroid Build Coastguard WorkerMonitors are inflated, and `Monitor` structs are allocated on demand, when an operation is
51*795d594fSAndroid Build Coastguard Workerperformed that cannot be accommodated with just the lock word. This normally happens when we need
52*795d594fSAndroid Build Coastguard Workerto store a hash code in a locked object, when there is lock contention, or when `Object.wait` is
53*795d594fSAndroid Build Coastguard Workerexecuted. (Notification on an object with no waiters is trivial and does not require inflation.)
54*795d594fSAndroid Build Coastguard WorkerIn the 64-bit case, the `monitor_chunks_` data structure may also need to be extended at this time
55*795d594fSAndroid Build Coastguard Workerto allow mapping of an additional `MonitorId`.
56*795d594fSAndroid Build Coastguard Worker
57*795d594fSAndroid Build Coastguard WorkerIf we have to inflate a lock that is currently held by another Thread B, we must suspend B while
58*795d594fSAndroid Build Coastguard Workerupdating the data structure representing the lock B holds. When the lock is later released by B,
59*795d594fSAndroid Build Coastguard Workerit will notice the change and operate on the fat lock representation instead.
60*795d594fSAndroid Build Coastguard Worker
61*795d594fSAndroid Build Coastguard WorkerMonitor deflation
62*795d594fSAndroid Build Coastguard Worker-----------------
63*795d594fSAndroid Build Coastguard WorkerMonitors are deflated, and the `Monitor` structs associated with deflated monitors are reclaimed
64*795d594fSAndroid Build Coastguard Workeras part of `Heap::Trim()` by invoking `SweepMonitorList()` with an `IsMarkedVisitor` that deflates
65*795d594fSAndroid Build Coastguard Workerunheld monitors with no waiters. This is done with all other threads suspended.
66*795d594fSAndroid Build Coastguard Worker
67*795d594fSAndroid Build Coastguard WorkerMonitors are also reclaimed, again via `SweepMonitorList()`, in `SweepSystemWeaks()`, if the
68*795d594fSAndroid Build Coastguard Workercorresponding object was not marked.
69*795d594fSAndroid Build Coastguard Worker
70*795d594fSAndroid Build Coastguard Worker(There is one other use of monitor deflation from `ImageWriter`. That does not maintain
71*795d594fSAndroid Build Coastguard Worker`MonitorList`. It relies on the fact that the dex2oat process is single-threaded, and the heap is
72*795d594fSAndroid Build Coastguard Workerabout to be discarded.)
73*795d594fSAndroid Build Coastguard Worker
74