[13] RFR (S): 8188133: C2: Static field accesses in clinit can trigger deoptimizations

Vladimir Kozlov vladimir.kozlov at oracle.com
Mon Feb 4 19:39:50 UTC 2019

On 2/4/19 10:42 AM, Vladimir Ivanov wrote:
> On 01/02/2019 10:32, Vladimir Kozlov wrote:
>> I am more concern about C2 hidden assumptions about classes it compiles and static fields accesses order than about 
>> Java correctness of executing code in static initializers.
>> On other hand we are at the beginning of JDK 13 and can do this experiment to see how it goes. Okay but please test it 
>> may be up-to tier7 before push.
>> Changes itself seem fine.
> Thanks, Vladimir. Tier1-7 testing finished successully. Will push the patch today.

Thank you for testing more.

Vladimir K

> Best regards,
> Vladimir Ivanov
>> On 2/1/19 10:13 AM, Vladimir Ivanov wrote:
>>>> So this is the case for OSR compilation of <clinit> with hot loop (iterations > 10000). Should we care about such 
>>>> cases?
>>>> We want people to write simple <clinit> so we can serialize results - this case is opposite direction.
>>> It's definitely a corner case and having long-running static initializers is discouraged, but I don't agree that it 
>>> should be ignored by JITs.
>>> The faster <clinit> is finished the better for startup & warmup: as you noted, <clinit> serializes execution and may 
>>> end up blocking the rest of the program. So, there are clear incentives to optimize <clinit>, though it may not be 
>>> the most important case to care about.
>>>> I understand that JITed code should perform better than Interpreter. And we should fix regression in jdk 9.
>>> Regression is handled separately (JDK-8192070) and it is not specific to static initializers. With this enhancement, 
>>> I'm interested solely in how JITs handle <clinit>.
>>>> There are several conditions for inlining. What if a called method is not inlined even with your relaxed condition? 
>>>> We will still deoptimize it on each iteration. Right?
>>> Yes, proposed patch doesn't solve the general case. It just extends existing heuristics. If iniling fails, callee has 
>>> to deoptimize.
>>>> I am fine to allow access to static fields from <clinit> code but I am not sure about allowing to inline general 
>>>> methods when class is not fully initialized. Can we limit what methods should be inlined? Leaf methods? Small code? 
>>>> No loops?
>>> We definitely can, but I don't see compelling reasons to do so. It's perfectly fine to run any code in the context of 
>>> static initializer. The only limitation is - only the thread which runs clinit is allowed to do so. I believe having 
>>> clinit as the root of compilation is a strong guarantee of that invariant.
>>>> I would prefer to not compile such <clinit> at all (if it has hot calls).
>>> It would have negative consequences on startup and warmup.
>>> In this particular case, the problem is not in clinit itself, but the code it calls. Methods accessing static members 
>>> have the very same problem when compiled into a separate nmethod.
>>> Best regards,
>>> Vladimir Ivanov
>>>> On 1/31/19 11:29 AM, Vladimir Ivanov wrote:
>>>>> http://cr.openjdk.java.net/~vlivanov/8188133/webrev.00
>>>>> https://bugs.openjdk.java.net/browse/JDK-8188133
>>>>> The test case in the bug demonstrates a pathological case with long-running static initializer: though it's allowed 
>>>>> to access static fields from the thread performing the initialization, C2 can't prove that in general.
>>>>> While solving the general problem doesn't seem worth the effort (requires barriers on method entries), I propose to 
>>>>> extend the logic to cover simple cases: when static initializer is the root of the compilation, all accesses to 
>>>>> static fields of the corresponding class are allowed. It extends the coverage to all inlinees from OSR compilation 
>>>>> of clinit.
>>>>> Testing: hs-precheckin-comp, tier1-5
>>>>> Best regards,
>>>>> Vladimir Ivanov

More information about the hotspot-compiler-dev mailing list