Hopefully the following is a statement of fact:
Currently the status word for an object looks like either:
TTTT TTTT TTTT TTTT TTTT TTHH AAAA AAAA (normal)
TTTT TTTT TTTT TTTT TTTT HHHH HHHH HHAA (GC trace)
T = thin lock bits
H = hash code state bits
A = available for use by GCHeader and/or MiscHeader.
the thin lock bits hold:
1 bit for the thin lock header, for lock reservation one could imagine a 2nd bit being used
14 bits to hold the thread ID of the thread holding the lock for the object
any remaining bits to hold a recursion count for how many times a thread holds the lock for an object
if the thin lock doesn't work the lock header bit says the contents of the bits is the heavy lock ID.
The 2bit hashcode state has one of the following values:
0 - unhashed - no one has tried to get the hash code of this object
1 - hashed - some one has tried to get the hash code of the object
2 - hashed & moved - we've moved the object and therefore had to make a copy of the hash code to enable us to compute the same hash code value in the future
The 10bit hashcode is just a counter that wraps around.
The available bits are used by MMTk and the number of bits used varies. Typically 2 bits are used for tracking the space an object is in and for marking. There is support for 4 bits for marking and 7bits may be used for reference counting. The number of bits used can vary due to properties loaded during boot image writing.
The object model supports either bit or byte accesses to the status word.
Here are my feelings about the way we do this layout (and may have been warped by me misunderstanding the code):
1) When we use available bits we nearly always do it at the granularity of a word.
2) One can imagine that reading and writing a byte is more efficient than masking... a word. The only place this seems to happen is MarkSweepSpace. We may well want some optimization so that byte values can be read/written, for example iterating over every status word setting the available byte to 0. This doesn't happen currently.
3) If bits are unused in the header then we are reducing the number of threads we support, the recursion count for holding a thread, the bits used in the counter variant of the hash code.
4) the GC trace header that uses a counter doesn't support garbage collectors requiring >2 bits such as reference counting
5) our current "available bits" implementation in the object model is based around the worst case expectations of MMTk and as such is conservative
6) as a lot of the code that uses the object model is trying as much as possible to use constants, there are boot strap issues.
I think we should fix the object model so that each GC can release the optimal number of bits for other uses in the status word. We need to make this configurable and fault when errors occur.
We eventually can play games with the object layout to see if there are architectural sweet spots. For example, the hash code bits could be tested by an 8 bit immediate mask if they weren't at bits 9 and 10.