JDK-8163880 : Constant pool caching of fields inhibited/delayed unnecessarily
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-08-11
  • Updated: 2016-11-23
  • Resolved: 2016-08-29
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.
JDK 9
9 b138Fixed
Related Reports
Relates :  
Relates :  
Description
Aurora is measuring a startup regression in 9-b129 on all platforms with all the startup apps in 9-b129. JVM displacement runs indicate that there are potentially both JDK and JVM sources of this regression. It's interesting that the Javac/Javadoc Startup benchmarks indicate their regression is in the JVM, but the Startup3 apps show both JVM and JDK sources. So there maybe be more than one issue involved here. 

Since there's the potential for more than one regression here, it might be best if each regression opened a corresponding bug, and once those bugs are resolved this one can be considered resolved.
Comments
Will not backport to pre-JDK 9.
23-11-2016

Updated webrev: http://cr.openjdk.java.net/~zmajo/8163880/webrev.01/
24-08-2016

I went through the changes by JDK-8160527 http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/29ed49c42486 to see if there are any optimization opportunities. I've found three problems that lead to a possible performance degradation. Please see details below. Problem #1 JDK-8160527 changed constant pool (CP) cache resolution for put instructions (putfield, putstatic, nofast_putfield). With that change, CP caching of put instructions targeting final fields is inhibited, which causes significant overhead. Consider the following example: If the field is final, is_put==true, the class initialization is already done (uninitialized_static==false), CP caching is inhibited http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/29ed49c42486#l1.30 Before JDK-8160527, CP caching was delayed until class initialization was being performed (uninitialized_static==true). But caching was eventually set up (once class initialization was complete). http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/29ed49c42486#l1.38 As a result of the changes by JDK-8160527, updates to final fields are continuously re-resolved (i.e., LinkResolver::resolve_field_access() is called on each update), which has a considerable overhead. It is not necessary that CP caching of all final field puts is inhibited. It is sufficient to do that for all puts to final fields for which the runtime detected updates from non-initializer methods (i.e., <clinit> and <init>). The reason for inhibiting caching for those fields is to make sure the appropriate IllegalAccessError is thrown at the proper code location (see JDK-8157181 for more background on this issue). Problem #2: CP caching of put instructions to non-final fields is delayed. Before JDK-8160527, if a non-put instruction was to resolve a field for the first time, resolution was enabled if that field was non-final. Consider is_put == false and info.access_flags().is_final() returning false below: http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/29ed49c42486#l1.38 With the changes by JDK-8160527, that is not the case. Consider the case when first resolution is by a non-put instruction, i.e., is_put == false and the field is not final: http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/29ed49c42486#l1.30 CP caching of the put instruction to a non-final field is delayed until a put instruction triggers resolution. That is, with JDK-8160527, CP caching of that put instruction happens later than it used to happen before (before JDK-8160527). CP caching of such instructions should happen at the same time as it used to happen before. Problem #3: Delaying/inhibiting CP caching of fields with invalid updates is required only for class files with version number >= JDK 9. The reason is that we are enforcing the updated JVM Specification only for those class files and that is likely to stay that way (see JDK-8159215 for more details). Here is a changeset that implements the solution for Problems #1 and #2. http://cr.openjdk.java.net/~zmajo/code/8163880/webrev_1_2/ Here is a changeset that implements the solution for Problems #1, #2, and #3. http://cr.openjdk.java.net/~zmajo/code/8163880/webrev_1_2_3/ I'm currently evaluating performance with both solutions, I hope some of them to mitigate the problem we're seeing.
22-08-2016

Here are the results of the performance evaluation: - zoltan.majo.8163880.baseline.01: recent checkout from hs-comp -- regression present - zoltan.majo.8163880.backout.01: backout JDK-8160527 -- regression gone - zoltan.majo.8163880.problem_1_2.attempt.01: patch that includes the solution to Problem #1 and #2 -- regression gone - zoltan.majo.8163880.problem_1_2_3.attempt.01: patch that includes the solution to Problem #1, #2, and #3 -- regression gone
22-08-2016

I don't see any aspect of this bug that should stay confidential. So I'm setting the security level of this bug to "None" (i.e., open).
22-08-2016

ILW=moderate startup regression,all startup benchmarks,no workaround=MMH=P3 Please feel free to update ILW with more reasonable values.
19-08-2016

From my local testing this is due to r11584 http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/29ed49c42486 I will make JPRT builds and a dev-submit to get more coverage.
17-08-2016

The problem seems to be in hotspot between r11577 up to r11596, there are a few changes in that range to try.
17-08-2016

ILW=M (perf regression), H (all startup metrics, all platforms), H (no known workaround) therefore initial priority is set to P2
11-08-2016