JDK-8334754 : C2: Optimize accesses to provably final instance fields
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 24
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2024-06-21
  • Updated: 2024-06-21
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 :  
Relates :  
Relates :  
Description
As of now, C2 constant folds accesses to static finals and a limited set of instance final fields which are explicitly marked as trusted by the JVM. But there's another optimization opportunity: aggressively common loads from instance final fields. 

Compared to static case, instance final fields pose some new challenges.  
In particular, premature publication of partially initialized instance. Even though JVMS forbids any final field updates outside constructor (enforced by the verifier), partially constructed instance can become visible before its initialization is finished. It happens when partially constructed instance leaks from the constructor (either as method arguments/receiver or gets published on the Java heap). Another problematic scenario comes from possibility of post-initialization field modifications through Reflection, JNI, or Unsafe APIs.

When it comes to partially initialized instances, JVM can guarantee for some classes that all (or some subset) of their final fields are always properly initialized. It can be achieved statically by performing static analysis of the bytecodes involved in instance construction. 

For such provably final fields, it becomes safe for C2 to perform more aggressive optimizations. For every instance its provably final fields are statically guaranteed to be fully initialized unless the instance is allocated locally. It enables some simplifications of IR shapes: an access to fully initialized final field can safely ignore memory state and only rely on data dependency on field holder for proper scheduling (as an existing example, LoadKlass uses immutable memory).   

Local allocations require special handling. As with Allocate/Initialize, new barrier is needed to explicitly mark the point in the IR where provably final fields are properly initialized, but the instance hasn't escaped yet. It turns existing allocation pattern into 3 phases (Allocate/Initialize/Publish). Allocate produces a raw pointer, Initialize produces a managed oop which can be safely observed by the rest of the JVM, and Publish produces a fully initialized instance (when it comes to provably final instance fields).  

Exact location of Publish barrier can be determined by the bytecode static analysis.