RFR: 8213486: SIGSEGV in CompiledMethod::cleanup_inline_caches_impl with AOT

Erik Österlund erik.osterlund at oracle.com
Wed Nov 21 14:28:26 UTC 2018

Hi Dean,

On 2018-11-20 19:21, dean.long at oracle.com wrote:
> OK.  I agree it makes sense to move the unloading from CompiledMethod 
> to nmethod.  I was just curious what problem you were running into 
> with AOT,
> because the iterators look OK to me. 

I am also curious!

> You probably ran into trouble here:
> // Clean inline caches pointing to both zombie and not_entrant methods 
> *if* (clean_all 
> <https://java.se.oracle.com/source/s?defs=clean_all&project=jdk-jdk> 
> || !nm 
> <https://java.se.oracle.com/source/s?defs=nm&project=jdk-jdk>->is_in_use 
> <https://java.se.oracle.com/source/s?defs=is_in_use&project=jdk-jdk>() 
> || nm 
> <https://java.se.oracle.com/source/s?defs=nm&project=jdk-jdk>->is_unloading 
> <https://java.se.oracle.com/source/s?defs=is_unloading&project=jdk-jdk>() 
> || (nm 
> <https://java.se.oracle.com/source/s?defs=nm&project=jdk-jdk>->method 
> <https://java.se.oracle.com/source/s?defs=method&project=jdk-jdk>()->code 
> <https://java.se.oracle.com/source/s?defs=code&project=jdk-jdk>() != 
> nm <https://java.se.oracle.com/source/s?defs=nm&project=jdk-jdk>)) {
> because !is_in_use() would be false for the not_used state.

No, if it is not_used, then !is_in_use() will return true, and therefore 
nm->is_unloading() will not be called. In fact, upon crashing here, I 
know that th AOT method is in fact in_use.

So now I am also trying to figure out how the iterators manage to miss 
the AOT method. I just know with pretty high certainty that they do.


> dl
> On 11/20/18 3:12 AM, Erik Österlund wrote:
>> Hi Dean,
>> Yeah I think I misunderstood what I observed. So what I know is that 
>> in the code cache unloading, I'm not getting all is_alive() AOT 
>> methods into my iterator, which messes up the assumptions made by the 
>> epoch based scheme for AOT methods.
>> I noticed that in AOTCodeHeap::sweep_dependent_methods(int* indexes, 
>> int methods_cnt) we make AOTCompiledMethods "invalid" in the AOT 
>> heap, making it no longer observable from the iterators. Then it 
>> calls the VM_Deoptimize vm operation after. Throughout all this, the 
>> AOTCompiledMethod is alive(), yet when the iterators ask for all 
>> is_alive() AOTCompiledMethods, it won't be visible. But I suppose IC 
>> caches may still reference these methods and check if it 
>> is_unloading, and then we blow up. There may possibly be multiple 
>> ways for is_alive() AOTCompiledMethods to not be visible from 
>> iterators yet be visible through IC caches using the "invalid" state 
>> in the .
>> Anyway, the fix is the same: stop doing the epoch state thingey for 
>> is_unloading() on AOTCompiledMethod where it isn't needed, and 
>> doesn't seem to play well with the rather different life cycle it 
>> has, and just return false instead.
>> Thanks,
>> /Erik
>> On 2018-11-20 00:00, dean.long at oracle.com wrote:
>>> Hi Erik,
>>> On 11/19/18 12:42 PM, Erik Österlund wrote:
>>>> ...except it looks like for AOTCompiledMethods when running with 
>>>> tiered compilation, may first be is_alive(), then become 
>>>> !is_alive() for a while, and then get resurrected to is_alive() 
>>>> using make_entrant().
>>> this doesn't sounds quite right.  AOTCompiledMethods aren't allowed 
>>> to transition to zombie (!alive), only not_used or not_entrant, 
>>> which should still have is_alive() returning true. Maybe some code 
>>> is using is_not_entrant() instead of !is_alive()?
>>> dl

More information about the hotspot-dev mailing list