OpenJDK / portola / portola
changeset 57244:252a8bb9f587
8234426: Sweeper should not CompiledIC::set_to_clean with ICStubs for is_unloading() nmethods
Reviewed-by: stefank, thartmann
author | eosterlund |
---|---|
date | Tue, 03 Dec 2019 16:13:37 +0000 |
parents | 0c4b36eb590d |
children | cfed0da56a7b |
files | src/hotspot/share/code/compiledMethod.cpp |
diffstat | 1 files changed, 14 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/hotspot/share/code/compiledMethod.cpp Wed Dec 04 00:06:41 2019 +0800 +++ b/src/hotspot/share/code/compiledMethod.cpp Tue Dec 03 16:13:37 2019 +0000 @@ -489,7 +489,20 @@ if (nm != NULL) { // Clean inline caches pointing to both zombie and not_entrant methods if (clean_all || !nm->is_in_use() || nm->is_unloading() || (nm->method()->code() != nm)) { - if (!ic->set_to_clean(from->is_alive())) { + // Inline cache cleaning should only be initiated on CompiledMethods that have been + // observed to be is_alive(). However, with concurrent code cache unloading, it is + // possible that by now, the state has been racingly flipped to unloaded if the nmethod + // being cleaned is_unloading(). This is fine, because if that happens, then the inline + // caches have already been cleaned under the same CompiledICLocker that we now hold during + // inline cache cleaning, and we will simply walk the inline caches again, and likely not + // find much of interest to clean. However, this race prevents us from asserting that the + // nmethod is_alive(). The is_unloading() function is completely monotonic; once set due + // to an oop dying, it remains set forever until freed. Because of that, all unloaded + // nmethods are is_unloading(), but notably, an unloaded nmethod may also subsequently + // become zombie (when the sweeper converts it to zombie). Therefore, the most precise + // sanity check we can check for in this context is to not allow zombies. + assert(!from->is_zombie(), "should not clean inline caches on zombies"); + if (!ic->set_to_clean(!from->is_unloading())) { return false; } assert(ic->is_clean(), "nmethod " PTR_FORMAT "not clean %s", p2i(from), from->method()->name_and_sig_as_C_string());