RFR: 8303512: Race condition when computing is_loaded property of TypePtr::InterfaceSet [v5]
Tobias Hartmann
thartmann at openjdk.org
Mon May 15 11:09:56 UTC 2023
On Mon, 15 May 2023 06:41:01 GMT, Tobias Hartmann <thartmann at openjdk.org> wrote:
>> [JDK-8297933](https://bugs.openjdk.org/browse/JDK-8297933) introduced a race condition among compiler threads computing `TypePtr::InterfaceSet::_is_loaded` for shared types (for example, for [TypeInstPtr::NOTNULL](https://github.com/openjdk/jdk/blob/5726d31e56530bbe7dee61ae04b126e20cb3611d/src/hotspot/share/opto/type.cpp#L545)). One thread can set `_is_loaded_computed` before setting `_is_loaded`:
>>
>> https://github.com/openjdk/jdk/blob/5726d31e56530bbe7dee61ae04b126e20cb3611d/src/hotspot/share/opto/type.cpp#L3473-L3482
>>
>> while another thread can already access `is_loaded()` and wrongly observe `_is_loaded = false`:
>>
>> https://github.com/openjdk/jdk/blob/5726d31e56530bbe7dee61ae04b126e20cb3611d/src/hotspot/share/opto/type.cpp#L3464-L3468
>>
>> As a result, the klass of a `TypePtr` can be loaded while the interfaces it implements appear to be not loaded.
>>
>> Another problem is that `TypePtr::InterfaceSet::eq` does not take the `_is_loaded` / `_is_loaded_computed` fields into account:
>>
>> https://github.com/openjdk/jdk/blob/5726d31e56530bbe7dee61ae04b126e20cb3611d/src/hotspot/share/opto/type.cpp#L3290-L3301
>>
>> A loaded type can therefore be replaced by an unloaded type during GVN.
>>
>> In the case of the failure reported by this bug, `LibraryCallKit::inline_native_hashcode` first null checks the receiver and updates the type. Due to the issues described above, the null-free type is GVN'ed with it's unloaded counterpart and propagated to another, redundant null check emitted by `LibraryCallKit::generate_method_call` (I filed [JDK-8307625](https://bugs.openjdk.org/browse/JDK-8307625) to remove it). Since the type is now unloaded, an uncommon trap is emitted and parsing is stopped(). We crash when trying to de-reference `GraphKit::_map->_jvms` which is NULL (in debug we would hit an assert).
>>
>> Another failure mode is reported by [JDK-8305339](https://bugs.openjdk.org/browse/JDK-8305339). Both failures are extremely intermittent and I was never able to reproduce them.
>>
>> The fix I propose is to completely remove the `_is_loaded` logic because if a klass is loaded, the interface that it implements should be loaded as well. I added an assert to verify this. Higher tier testing is still running.
>>
>> In addition, I noticed some `#ifdef DEBUG` checks where `DEBUG` is never defined. I replaced them by `#ifdef ASSERT` and fixed the verification code that failed to build.
>>
>> Thanks,
>> Tobias
>
> Tobias Hartmann has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains seven additional commits since the last revision:
>
> - Merge branch 'master' into JDK-8303512
> - Removed interface_handling argument
> - Refactoring
> - Eager computation to avoid racy update of remaining fields
> - Re-ordering of _computed fields initialization
> - Reverted unrelated change
> - 8303512: Race condition when computing is_loaded property of TypePtr::InterfaceSet
False alarm. I'm integrating this now.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/13868#issuecomment-1547648664
More information about the hotspot-compiler-dev
mailing list