File tree Expand file tree Collapse file tree 4 files changed +26
-0
lines changed
Expand file tree Collapse file tree 4 files changed +26
-0
lines changed Original file line number Diff line number Diff line change @@ -174,6 +174,9 @@ rb_iseq_free(const rb_iseq_t *iseq)
174174 RUBY_ASSERT (rb_yjit_live_iseq_count > 0 );
175175 rb_yjit_live_iseq_count -- ;
176176 }
177+ #endif
178+ #if USE_ZJIT
179+ rb_zjit_iseq_free (iseq );
177180#endif
178181 ruby_xfree ((void * )body -> iseq_encoded );
179182 ruby_xfree ((void * )body -> insns_info .body );
Original file line number Diff line number Diff line change @@ -22,6 +22,7 @@ void rb_zjit_invalidate_no_ep_escape(const rb_iseq_t *iseq);
2222void rb_zjit_constant_state_changed (ID id );
2323void rb_zjit_iseq_mark (void * payload );
2424void rb_zjit_iseq_update_references (void * payload );
25+ void rb_zjit_iseq_free (const rb_iseq_t * iseq );
2526void rb_zjit_before_ractor_spawn (void );
2627void rb_zjit_tracing_invalidate_all (void );
2728#else
Original file line number Diff line number Diff line change @@ -128,6 +128,17 @@ pub extern "C" fn rb_zjit_iseq_update_references(payload: *mut c_void) {
128128 with_time_stat ( gc_time_ns, || iseq_update_references ( payload) ) ;
129129}
130130
131+ /// GC callback for finalizing an ISEQ
132+ #[ unsafe( no_mangle) ]
133+ pub extern "C" fn rb_zjit_iseq_free ( iseq : IseqPtr ) {
134+ if !ZJITState :: has_instance ( ) {
135+ return ;
136+ }
137+ // TODO(Shopify/ruby#682): Free `IseqPayload`
138+ let invariants = ZJITState :: get_invariants ( ) ;
139+ invariants. forget_iseq ( iseq) ;
140+ }
141+
131142/// GC callback for updating object references after all object moves
132143#[ unsafe( no_mangle) ]
133144pub extern "C" fn rb_zjit_root_update_references ( ) {
Original file line number Diff line number Diff line change @@ -68,6 +68,17 @@ impl Invariants {
6868 self . update_no_ep_escape_iseq_patch_points ( ) ;
6969 }
7070
71+ /// Forget an ISEQ when freeing it. We need to because a) if the address is reused, we'd be
72+ /// tracking the wrong object b) dead VALUEs in the table can means we risk passing invalid
73+ /// VALUEs to `rb_gc_location()`.
74+ pub fn forget_iseq ( & mut self , iseq : IseqPtr ) {
75+ // Why not patch the patch points? If the ISEQ is dead then the GC also proved that all
76+ // generated code referencing the ISEQ are unreachable. We mark the ISEQs baked into
77+ // generated code.
78+ self . ep_escape_iseqs . remove ( & iseq) ;
79+ self . no_ep_escape_iseq_patch_points . remove ( & iseq) ;
80+ }
81+
7182 /// Update ISEQ references in Invariants::ep_escape_iseqs
7283 fn update_ep_escape_iseqs ( & mut self ) {
7384 let updated = std:: mem:: take ( & mut self . ep_escape_iseqs )
You can’t perform that action at this time.
0 commit comments