YJIT: Free pages after ObjectSpace API usages (#6676)

This commit is contained in:
Takashi Kokubun 2022-11-07 07:48:26 -08:00 коммит произвёл GitHub
Родитель ca0b592673
Коммит 7442cb461b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
1 изменённых файлов: 15 добавлений и 13 удалений

Просмотреть файл

@ -563,23 +563,14 @@ impl CodeBlock {
pages_in_use[*page] = true; pages_in_use[*page] = true;
} }
}); });
// Outlined code generated by CodegenGlobals::init() should also be kept.
for page in CodegenGlobals::get_ocb_pages() {
pages_in_use[*page] = true;
}
// Let VirtuamMem free the pages
let mut freed_pages: Vec<usize> = pages_in_use.iter().enumerate()
.filter(|&(_, &in_use)| !in_use).map(|(page, _)| page).collect();
self.free_pages(&freed_pages);
// Avoid accumulating freed pages for future code GC // Avoid accumulating freed pages for future code GC
for_each_off_stack_iseq_payload(|iseq_payload: &mut IseqPayload| { for_each_off_stack_iseq_payload(|iseq_payload: &mut IseqPayload| {
iseq_payload.pages.clear(); iseq_payload.pages.clear();
}); });
// Outlined code generated by CodegenGlobals::init() should also be kept.
// Append virtual pages in case RubyVM::YJIT.code_gc is manually triggered. for page in CodegenGlobals::get_ocb_pages() {
let mut virtual_pages: Vec<usize> = (self.num_mapped_pages()..self.num_virtual_pages()).collect(); pages_in_use[*page] = true;
freed_pages.append(&mut virtual_pages); }
// Invalidate everything to have more compact code after code GC. // Invalidate everything to have more compact code after code GC.
// This currently patches every ISEQ, which works, but in the future, // This currently patches every ISEQ, which works, but in the future,
@ -591,6 +582,17 @@ impl CodeBlock {
// can be safely reset to pass the frozen bytes check on invalidation. // can be safely reset to pass the frozen bytes check on invalidation.
CodegenGlobals::set_inline_frozen_bytes(0); CodegenGlobals::set_inline_frozen_bytes(0);
// Let VirtuamMem free the pages
let mut freed_pages: Vec<usize> = pages_in_use.iter().enumerate()
.filter(|&(_, &in_use)| !in_use).map(|(page, _)| page).collect();
// ObjectSpace API may trigger Ruby's GC, which marks gc_offsets in JIT code.
// So this should be called after for_each_*_iseq_payload and rb_yjit_tracing_invalidate_all.
self.free_pages(&freed_pages);
// Append virtual pages in case RubyVM::YJIT.code_gc is manually triggered.
let mut virtual_pages: Vec<usize> = (self.num_mapped_pages()..self.num_virtual_pages()).collect();
freed_pages.append(&mut virtual_pages);
if let Some(&first_page) = freed_pages.first() { if let Some(&first_page) = freed_pages.first() {
let mut cb = CodegenGlobals::get_inline_cb(); let mut cb = CodegenGlobals::get_inline_cb();
cb.write_pos = cb.get_page_pos(first_page); cb.write_pos = cb.get_page_pos(first_page);