JDK-8016581 : JSR 292: invokeExact (invokehandle) operations should profile method handle behavior forms
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: hs25,8,9,10
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2013-06-13
  • Updated: 2018-10-05
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Relates :  
Description
Method handles, like inner classes, are encapsulated behavior and values, and can be type-profiled for optimistic compilation.  The required profiling is different, however, since it needs to look at the MethodHandle.form.vmentry field, rather than the Object._klass field.  Since method handle invocation is done with a special hidden bytecode "invokehandle", the profiling machinery should be modified to capture that extra data when executing "invokehandle" instructions.

Background:

A method handle's meaning or behavior breaks into three parts:
1. the compiled bytecode of its LambdaForm (MethodHandle.form.vmentry)
2. the constants embedded in the LambdaForm expressions
3. bound values stored in the method handle itself (as a BoundMethodHandle subclass)

Parts 1 and 2 correspond to the (often anonymous) class of an inner class object which adapts some functional interface.  Part 3 corresponds to the instance variables of that object.  Normal class-based type profiling in the JVM allows the JIT to produce good code for inner class objects in many cases.

Currently, part 2 is merged into part 1, because bytecodes are customized to contain all LF constants.  JDK-8001106 aims share bytecodes (part 1) among many similar LFs, where the only differences are constant arguments stored in the LF expressions.

The profiling of method handles therefore has three possible levels:
A. (Coarse) Detect call sites with one or two distinct bytecode (vmentry values) and optimistically compile code that loads parts 2 and 3 as non-constants.
B. (Medium) Detect call sites with one or two distinct lambda forms (form values) and optimistically compile code that loads part 3 as non-constants.  (Most similar to inner classes.)
C. (Fine) Detect call sites with one or two distinct method handles (receiver values) and optimistically compile code that inlines the whole method handle.

Case C. would be a subsumed by instance profiling, as in JDK-8016580.

Comments
Internally to method handle behaviors (MH.form.vmentry), calls to unknown (varying data dependent) methods are performed through linkToStatic, etc. The "pointer" to the target method is a MemberName reference (a "glue" object internal to method handle infrastructure). This pointer is stacked at the *end* of the argument list, *after* all normal arguments to the target method. The linkToStatic method is invoked by an "invokestatic" instruction. It may be worth while assigning just these "linker methods" their own "invokelinkermethod" internal VM instruction, whose behavior is identical to "invokestatic", but which perform type-C profiling on their *last* argument, the MemberName. That may allow inlining of more methods which are reached by these linkage methods. On the other hand, normal constant propagation will also present constant MemberName pointers to these linkage methods, and C2's optimizer (CallGenerator::for_method_handle_inline) looks for these and will inline them. Type-C profiling would provide another source of constant MemberName pointers to this optimization.
26-03-2014

The receiver class (Klass*) profiling done at invokevirtual is useless for monomorphic types; is it useless for MHs? For MHs this profile has some significance, since each bound MH species has its own data layout and (hence) its own Klass*. But, each distinct LF (lambda form) "knows" which bound MH species it applies to. (This "knowing" could be made more explicit than it currently is.) So the LF has (or ought to have) a strict superset of the information normally collected in Klass* profiling. Therefore, we could reuse the profile slots used to profile Klass* values. There's another option, though, which may be better: The internal bytecode "invokehandle" is used to invoke MHs (both invokeExact and plain invoke). We could, if we want, allocate a larger or different MDO record for invokehandle, so that both Klass* and vmentry (profile type A) could be captured. The different layout for the MDO record of an invokehandle could also accommodate constant detection (profile type C), as a later add-on. See comment on JDK-8016580.
26-03-2014

Note that in the current code, part 2 of the behavior (embedded constants) are directly "ldc"-ed from the constant pool of the bytecodes, as soon as the vmentry is replaced by the custom-compiled bytecode. This means that part 2 is mainly relevant to LF interpreter functions like LambdaForm.interpret_L. For warm MHs, the MH content splits cleanly between code (the form.vmentry, part 1) and data (the BoundMethodHandle fields, if any). Therefore, profiling options A and B are equivalent, except for cold MHs that are still being interpreted. I think A and C are the two sweet spots for profiling, with A being most broadly applicable. C is a "golden object" optimization (per call site) which detects and favors a single, unvarying receiver reference, as noted in JDK-8016580. Profiling type C is probably better applied to a wider range of receiver types, not just MHs. But A seems to be the best one to try first, because in many cases where the receiver is non-varying, just inlining its (non-varying) behavior (whether Klass* or vmentry) is enough to make the code fold up.
26-03-2014

8-pool is an invalid affects version. Set 8 and hs25.
12-11-2013