This file contains most of the code necessary for supporting VarHandle in native images. The
actual intrinsification of VarHandle accessors is in hosted-only code in the
IntrinsifyMethodHandlesInvocationPlugin.
The VarHandle implementation in the JDK uses some invokedynamic and method handles, but also a
lot of explicit Java code (a lot of it automatically generated): The main entry point from the
point of view of the user is the class VarHandle, which contains signature-polymorphic method
prototypes for the various access modes. However, we do not need to do anything special for the
VarHandle class: when we parse bytecode, all the bootstrapping has already happened on the Java
HotSpot VM, and the bytecode parser already sees calls to guard methods defined in
VarHandleGuards. Method of that class are the intrinsification root for the
IntrinsifyMethodHandlesInvocationPlugin. The intrinsification removes all the method handle
invocation logic and reduces the logic to a single call to the actual access logic. This logic is
in various automatically generated accessor classes named
"VarHandle{Booleans|Bytes|Chars|Doubles|Floats|Ints|Longs|Shorts|Objects}.{Array|FieldInstanceReadOnly|FieldInstanceReadWrite|FieldStaticReadOnly|FieldStaticReadWrite}".
The intrinsification must not inline these methods, because they contain complicated logic.
The accessor classes for field access (both instance and static field access) store the offset of
the field that is used for Unsafe memory access. We need to 1) properly register these fields as
unsafe accessed so that our static analysis is correct, and 2) recompute the field offsets from
the hosted offsets to the runtime offsets. Luckily, we have all information to reconstruct the
original
Field
(see
VarHandleFeature.findVarHandleField(java.lang.Object)
). The registration for unsafe access
happens in an object replacer: the method
VarHandleFeature.processVarHandle(java.lang.Object)
is called for every object
(and therefore every VarHandle) that is reachable in the image heap. The field offset
recomputations are registered for all classes manually (a bit of code duplication on our side),
but all recomputations use the same custom field value recomputation handler:
VarHandleFieldOffsetComputer
.
For static fields, also the base of the Unsafe access needs to be changed to the static field
holder arrays defined in
StaticFieldsSupport
. We cannot do a recomputation to the actual
arrays because the arrays are only available after static analysis. So we inject accessor methods
instead that read our holder fields:
VarHandleFieldStaticBasePrimitiveAccessor
and
VarHandleFieldStaticBaseObjectAccessor
.
VarHandle access to arrays is the simplest case: we only need field value recomputations for the
array base offset and array index shift.