|
1 | | -use std::{collections::{HashMap, HashSet}}; |
| 1 | +use std::{collections::{HashMap, HashSet}, mem}; |
2 | 2 |
|
3 | 3 | use crate::{backend::lir::{asm_comment, Assembler}, cruby::{rb_callable_method_entry_t, ruby_basic_operators, src_loc, with_vm_lock, IseqPtr, RedefinitionFlag, ID}, hir::Invariant, options::debug, state::{zjit_enabled_p, ZJITState}, virtualmem::CodePtr}; |
4 | 4 |
|
@@ -26,6 +26,9 @@ pub struct Invariants { |
26 | 26 |
|
27 | 27 | /// Map from constant ID to patch points that assume the constant hasn't been redefined |
28 | 28 | constant_state_patch_points: HashMap<ID, HashSet<Jump>>, |
| 29 | + |
| 30 | + /// Set of patch points that assume that the interpreter is running with only one ractor |
| 31 | + single_ractor_patch_points: HashSet<Jump>, |
29 | 32 | } |
30 | 33 |
|
31 | 34 | /// Called when a basic operator is redefined. Note that all the blocks assuming |
@@ -200,3 +203,38 @@ pub extern "C" fn rb_zjit_constant_state_changed(id: ID) { |
200 | 203 | } |
201 | 204 | }); |
202 | 205 | } |
| 206 | + |
| 207 | +/// Track that JIT code for a patch point that assumes that the interpreter is running with only one ractor |
| 208 | +pub fn track_single_ractor_assumption(patch_point_ptr: CodePtr, side_exit_ptr: CodePtr) { |
| 209 | + let invariants = ZJITState::get_invariants(); |
| 210 | + invariants.single_ractor_patch_points.insert(Jump { |
| 211 | + from: patch_point_ptr, |
| 212 | + to: side_exit_ptr, |
| 213 | + }); |
| 214 | +} |
| 215 | + |
| 216 | +/// Callback for then Ruby is about to spawn a ractor. In that case we need to |
| 217 | +/// invalidate every block that is assuming single ractor mode. |
| 218 | +#[unsafe(no_mangle)] |
| 219 | +pub extern "C" fn rb_zjit_before_ractor_spawn() { |
| 220 | + // If ZJIT isn't enabled, do nothing |
| 221 | + if !zjit_enabled_p() { |
| 222 | + return; |
| 223 | + } |
| 224 | + |
| 225 | + with_vm_lock(src_loc!(), || { |
| 226 | + // Clear the set of blocks inside Invariants |
| 227 | + let jumps = mem::take(&mut ZJITState::get_invariants().single_ractor_patch_points); |
| 228 | + |
| 229 | + // Invalidate the blocks |
| 230 | + for jump in &jumps { |
| 231 | + let cb = ZJITState::get_code_block(); |
| 232 | + cb.with_write_ptr(jump.from, |cb| { |
| 233 | + let mut asm = Assembler::new(); |
| 234 | + asm_comment!(asm, "Single ractor mode is invalidated"); |
| 235 | + asm.jmp(jump.to.into()); |
| 236 | + asm.compile(cb).expect("can write existing code"); |
| 237 | + }); |
| 238 | + } |
| 239 | + }); |
| 240 | +} |
0 commit comments