The
@IntrinsicCandidate
annotation is specific to the
HotSpot Virtual Machine. It indicates that an annotated method
may be (but is not guaranteed to be) intrinsified by the HotSpot VM. A method
is intrinsified if the HotSpot VM replaces the annotated method with hand-written
assembly and/or hand-written compiler IR -- a compiler intrinsic -- to improve
performance. The
@IntrinsicCandidate
annotation is internal to the
Java libraries and is therefore not supposed to have any relevance for application
code.
Maintainers of the Java libraries must consider the following when
modifying methods annotated with
@IntrinsicCandidate
.
- When modifying a method annotated with
@IntrinsicCandidate
,
the corresponding intrinsic code in the HotSpot VM implementation must be
updated to match the semantics of the annotated method.
- For some annotated methods, the corresponding intrinsic may omit some low-level
checks that would be performed as a matter of course if the intrinsic is implemented
using Java bytecodes. This is because individual Java bytecodes implicitly check
for exceptions like
NullPointerException
and ArrayStoreException
.
If such a method is replaced by an intrinsic coded in assembly language, any
checks performed as a matter of normal bytecode operation must be performed
before entry into the assembly code. These checks must be performed, as
appropriate, on all arguments to the intrinsic, and on other values (if any) obtained
by the intrinsic through those arguments. The checks may be deduced by inspecting
the non-intrinsic Java code for the method, and determining exactly which exceptions
may be thrown by the code, including undeclared implicit RuntimeException
s.
Therefore, depending on the data accesses performed by the intrinsic,
the checks may include:
- null checks on references
- range checks on primitive values used as array indexes
- other validity checks on primitive values (e.g., for divide-by-zero conditions)
- store checks on reference values stored into arrays
- array length checks on arrays indexed from within the intrinsic
- reference casts (when formal parameters are
Object
or some other weak type)
- Note that the receiver value (
this
) is passed as a extra argument
to all non-static methods. If a non-static method is an intrinsic, the receiver
value does not need a null check, but (as stated above) any values loaded by the
intrinsic from object fields must also be checked. As a matter of clarity, it is
better to make intrinisics be static methods, to make the dependency on this
clear. Also, it is better to explicitly load all required values from object
fields before entering the intrinsic code, and pass those values as explicit arguments.
First, this may be necessary for null checks (or other checks). Second, if the
intrinsic reloads the values from fields and operates on those without checks,
race conditions may be able to introduce unchecked invalid values into the intrinsic.
If the intrinsic needs to store a value back to an object field, that value should be
returned explicitly from the intrinsic; if there are multiple return values, coders
should consider buffering them in an array. Removing field access from intrinsics
not only clarifies the interface with between the JVM and JDK; it also helps decouple
the HotSpot and JDK implementations, since if JDK code before and after the intrinsic
manages all field accesses, then intrinsics can be coded to be agnostic of object
layouts.
Maintainers of the HotSpot VM must consider the following when modifying
intrinsics.
- When adding a new intrinsic, make sure that the corresponding method
in the Java libraries is annotated with
@IntrinsicCandidate
and that all possible call sequences that result in calling the intrinsic contain
the checks omitted by the intrinsic (if any).
- When modifying an existing intrinsic, the Java libraries must be updated
to match the semantics of the intrinsic and to execute all checks omitted
by the intrinsic (if any).
Persons not directly involved with maintaining the Java libraries or the
HotSpot VM can safely ignore the fact that a method is annotated with
@IntrinsicCandidate
.
The HotSpot VM defines (internally) a list of intrinsics. Not all intrinsic
are available on all platforms supported by the HotSpot VM. Furthermore,
the availability of an intrinsic on a given platform depends on the
configuration of the HotSpot VM (e.g., the set of VM flags enabled).
Therefore, annotating a method with @IntrinsicCandidate
does
not guarantee that the marked method is intrinsified by the HotSpot VM.
If the CheckIntrinsics
VM flag is enabled, the HotSpot VM checks
(when loading a class) that (1) all methods of that class that are also on
the VM's list of intrinsics are annotated with @IntrinsicCandidate
and that (2) for all methods of that class annotated with
@IntrinsicCandidate
there is an intrinsic in the list.