YJIT: Avoid accumulating freed pages in the payload (#6657)
Co-Authored-By: Alan Wu <alansi.xingwu@shopify.com> Co-Authored-By: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> Co-authored-by: Alan Wu <alansi.xingwu@shopify.com> Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>
This commit is contained in:
parent
4a8cd9e8bc
commit
946bb34fb5
Notes:
git
2022-11-02 15:14:53 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
@ -6,6 +6,8 @@ use std::rc::Rc;
|
|||||||
use crate::backend::x86_64::JMP_PTR_BYTES;
|
use crate::backend::x86_64::JMP_PTR_BYTES;
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use crate::backend::arm64::JMP_PTR_BYTES;
|
use crate::backend::arm64::JMP_PTR_BYTES;
|
||||||
|
use crate::core::IseqPayload;
|
||||||
|
use crate::core::for_each_off_stack_iseq_payload;
|
||||||
use crate::core::for_each_on_stack_iseq_payload;
|
use crate::core::for_each_on_stack_iseq_payload;
|
||||||
use crate::invariants::rb_yjit_tracing_invalidate_all;
|
use crate::invariants::rb_yjit_tracing_invalidate_all;
|
||||||
use crate::stats::incr_counter;
|
use crate::stats::incr_counter;
|
||||||
@ -571,6 +573,10 @@ impl CodeBlock {
|
|||||||
let mut freed_pages: Vec<usize> = pages_in_use.iter().enumerate()
|
let mut freed_pages: Vec<usize> = pages_in_use.iter().enumerate()
|
||||||
.filter(|&(_, &in_use)| !in_use).map(|(page, _)| page).collect();
|
.filter(|&(_, &in_use)| !in_use).map(|(page, _)| page).collect();
|
||||||
self.free_pages(&freed_pages);
|
self.free_pages(&freed_pages);
|
||||||
|
// Avoid accumulating freed pages for future code GC
|
||||||
|
for_each_off_stack_iseq_payload(|iseq_payload: &mut IseqPayload| {
|
||||||
|
iseq_payload.pages.clear();
|
||||||
|
});
|
||||||
|
|
||||||
// Append virtual pages in case RubyVM::YJIT.code_gc is manually triggered.
|
// 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();
|
let mut virtual_pages: Vec<usize> = (self.num_mapped_pages()..self.num_virtual_pages()).collect();
|
||||||
|
@ -552,20 +552,39 @@ pub fn for_each_iseq<F: FnMut(IseqPtr)>(mut callback: F) {
|
|||||||
unsafe { rb_yjit_for_each_iseq(Some(callback_wrapper), (&mut data) as *mut _ as *mut c_void) };
|
unsafe { rb_yjit_for_each_iseq(Some(callback_wrapper), (&mut data) as *mut _ as *mut c_void) };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all on-stack ISEQ payloads
|
/// Iterate over all on-stack ISEQs
|
||||||
#[cfg(not(test))]
|
pub fn for_each_on_stack_iseq<F: FnMut(IseqPtr)>(mut callback: F) {
|
||||||
pub fn for_each_on_stack_iseq_payload<F: FnMut(&IseqPayload)>(mut callback: F) {
|
|
||||||
unsafe extern "C" fn callback_wrapper(iseq: IseqPtr, data: *mut c_void) {
|
unsafe extern "C" fn callback_wrapper(iseq: IseqPtr, data: *mut c_void) {
|
||||||
let callback: &mut &mut dyn FnMut(&IseqPayload) -> bool = std::mem::transmute(&mut *data);
|
let callback: &mut &mut dyn FnMut(IseqPtr) -> bool = std::mem::transmute(&mut *data);
|
||||||
|
callback(iseq);
|
||||||
|
}
|
||||||
|
let mut data: &mut dyn FnMut(IseqPtr) = &mut callback;
|
||||||
|
unsafe { rb_jit_cont_each_iseq(Some(callback_wrapper), (&mut data) as *mut _ as *mut c_void) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate over all on-stack ISEQ payloads
|
||||||
|
pub fn for_each_on_stack_iseq_payload<F: FnMut(&IseqPayload)>(mut callback: F) {
|
||||||
|
for_each_on_stack_iseq(|iseq| {
|
||||||
if let Some(iseq_payload) = get_iseq_payload(iseq) {
|
if let Some(iseq_payload) = get_iseq_payload(iseq) {
|
||||||
callback(iseq_payload);
|
callback(iseq_payload);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
let mut data: &mut dyn FnMut(&IseqPayload) = &mut callback;
|
}
|
||||||
unsafe { rb_jit_cont_each_iseq(Some(callback_wrapper), (&mut data) as *mut _ as *mut c_void) };
|
|
||||||
|
/// Iterate over all NOT on-stack ISEQ payloads
|
||||||
|
pub fn for_each_off_stack_iseq_payload<F: FnMut(&mut IseqPayload)>(mut callback: F) {
|
||||||
|
let mut on_stack_iseqs: Vec<IseqPtr> = vec![];
|
||||||
|
for_each_on_stack_iseq(|iseq| {
|
||||||
|
on_stack_iseqs.push(iseq);
|
||||||
|
});
|
||||||
|
for_each_iseq(|iseq| {
|
||||||
|
if !on_stack_iseqs.contains(&iseq) {
|
||||||
|
if let Some(iseq_payload) = get_iseq_payload(iseq) {
|
||||||
|
callback(iseq_payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
#[cfg(test)]
|
|
||||||
pub fn for_each_on_stack_iseq_payload<F: FnMut(&IseqPayload)>(mut _callback: F) {}
|
|
||||||
|
|
||||||
/// Free the per-iseq payload
|
/// Free the per-iseq payload
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user