There are several places in the VM where the resolved_klasses array is read
and the result is null-checked. All (or most) of those null checks should be
turned into asserts, since reads from the resolved_klasses array are
(almost) always preceded by checks of a CP tag, to see if it is the
value JVM_CONSTANT_Class. If it is, then the corresponding
resolved_klasses array entry is non-null.
This is a tricky invariant, since (a) the CP tag in question has a complex
state diagram (from unresolved to either resolved or error), and also (b)
the two words are sequentially (not atomically) updated.
However, when the tag changed to JVM_CONSTANT_Class,
a releasing store is always done, and the corresponding read
(maybe in a different thread) always makes an acquire.
In the writer, before the write of the tag, a releasing store was
done of a non-null Klass pointer to the resolved_klasses array.
The corresponding pointer read make an acquire. The pointer
read only happens after the first read (of the tag) witnesses
the value JVM_CONSTANT_Class.
It is therefore impossible (it appears to me) for the reader
to witness JVM_CONSTANT_Class as a tag, and then
read a null pointer from the resolved_klasses array.
If such a null pointer is possible to observe, the source
code needs to document how it can possibly happen.
If on the other hand such a null is not possible to observe,
the null checks in our code need to be turned into asserts.
and the result is null-checked. All (or most) of those null checks should be
turned into asserts, since reads from the resolved_klasses array are
(almost) always preceded by checks of a CP tag, to see if it is the
value JVM_CONSTANT_Class. If it is, then the corresponding
resolved_klasses array entry is non-null.
This is a tricky invariant, since (a) the CP tag in question has a complex
state diagram (from unresolved to either resolved or error), and also (b)
the two words are sequentially (not atomically) updated.
However, when the tag changed to JVM_CONSTANT_Class,
a releasing store is always done, and the corresponding read
(maybe in a different thread) always makes an acquire.
In the writer, before the write of the tag, a releasing store was
done of a non-null Klass pointer to the resolved_klasses array.
The corresponding pointer read make an acquire. The pointer
read only happens after the first read (of the tag) witnesses
the value JVM_CONSTANT_Class.
It is therefore impossible (it appears to me) for the reader
to witness JVM_CONSTANT_Class as a tag, and then
read a null pointer from the resolved_klasses array.
If such a null pointer is possible to observe, the source
code needs to document how it can possibly happen.
If on the other hand such a null is not possible to observe,
the null checks in our code need to be turned into asserts.