Skip to content

Commit 8df61bf

Browse files
authored
ZJIT: Support invalidating on method redefinition (ruby#13875)
ZJIT: Support invalidating method redefinition This commit adds support for the MethodRedefined invariant to be invalidated when a method is redefined. Changes: - Added CME pointer to the MethodRedefined invariant in HIR - Updated all places where MethodRedefined invariants are created to include the CME pointer - Added handling for MethodRedefined invariants in gen_patch_point to call track_cme_assumption, which registers the patch point for invalidation when rb_zjit_cme_invalidate is called This ensures that when a method is redefined, all JIT code that depends on that method will be properly invalidated.
1 parent dafc4e1 commit 8df61bf

File tree

6 files changed

+168
-69
lines changed

6 files changed

+168
-69
lines changed

test/ruby/test_zjit.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,31 @@ def test
10661066
}, call_threshold: 2
10671067
end
10681068

1069+
# ZJIT currently only generates a MethodRedefined patch point when the method
1070+
# is called on the top-level self.
1071+
def test_method_redefinition_with_top_self
1072+
assert_runs '["original", "redefined"]', %q{
1073+
def foo
1074+
"original"
1075+
end
1076+
1077+
def test = foo
1078+
1079+
test; test
1080+
1081+
result1 = test
1082+
1083+
# Redefine the method
1084+
def foo
1085+
"redefined"
1086+
end
1087+
1088+
result2 = test
1089+
1090+
[result1, result2]
1091+
}, call_threshold: 2
1092+
end
1093+
10691094
def test_module_name_with_guard_passes
10701095
assert_compiles '"Integer"', %q{
10711096
def test(mod)

vm_method.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ vm_cme_invalidate(rb_callable_method_entry_t *cme)
122122
RB_DEBUG_COUNTER_INC(cc_cme_invalidate);
123123

124124
rb_yjit_cme_invalidate(cme);
125+
rb_zjit_cme_invalidate(cme);
125126
}
126127

127128
static int

zjit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ void rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, boo
1212
void rb_zjit_profile_insn(enum ruby_vminsn_type insn, rb_execution_context_t *ec);
1313
void rb_zjit_profile_enable(const rb_iseq_t *iseq);
1414
void rb_zjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop);
15+
void rb_zjit_cme_invalidate(const rb_callable_method_entry_t *cme);
1516
void rb_zjit_invalidate_ep_is_bp(const rb_iseq_t *iseq);
1617
void rb_zjit_iseq_mark(void *payload);
1718
void rb_zjit_iseq_update_references(void *payload);
@@ -21,6 +22,7 @@ static inline void rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_cont
2122
static inline void rb_zjit_profile_insn(enum ruby_vminsn_type insn, rb_execution_context_t *ec) {}
2223
static inline void rb_zjit_profile_enable(const rb_iseq_t *iseq) {}
2324
static inline void rb_zjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop) {}
25+
static inline void rb_zjit_cme_invalidate(const rb_callable_method_entry_t *cme) {}
2426
static inline void rb_zjit_invalidate_ep_is_bp(const rb_iseq_t *iseq) {}
2527
#endif // #if USE_YJIT
2628

zjit/src/codegen.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::rc::Rc;
33

44
use crate::asm::Label;
55
use crate::backend::current::{Reg, ALLOC_REGS};
6-
use crate::invariants::track_bop_assumption;
6+
use crate::invariants::{track_bop_assumption, track_cme_assumption};
77
use crate::gc::{get_or_create_iseq_payload, append_gc_offsets};
88
use crate::state::ZJITState;
99
use crate::{asm::CodeBlock, cruby::*, options::debug, virtualmem::CodePtr};
@@ -494,6 +494,10 @@ fn gen_patch_point(jit: &mut JITState, asm: &mut Assembler, invariant: &Invarian
494494
let side_exit_ptr = cb.resolve_label(label);
495495
track_bop_assumption(klass, bop, code_ptr, side_exit_ptr);
496496
}
497+
Invariant::MethodRedefined { klass: _, method: _, cme } => {
498+
let side_exit_ptr = cb.resolve_label(label);
499+
track_cme_assumption(cme, code_ptr, side_exit_ptr);
500+
}
497501
_ => {
498502
debug!("ZJIT: gen_patch_point: unimplemented invariant {invariant:?}");
499503
return;

0 commit comments

Comments
 (0)