Invalidate CCs when cme is invalidated in marking

* Skip assertion when cc->klass is Qundef
* Invalidate CCs when cme is invalidated in marking
* Add additional assertions that CC references stay valid

Co-authored-by: Peter Zhu <peter@peterzhu.ca>
This commit is contained in:
John Hawthorn 2025-08-07 15:39:45 -07:00 committed by GitHub
parent d25eb1eb5c
commit c41c323f1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 17 additions and 3 deletions

View file

@ -30,16 +30,27 @@ mark_cc_entry_i(VALUE ccs_ptr, void *data)
VM_ASSERT(vm_ccs_p(ccs));
if (METHOD_ENTRY_INVALIDATED(ccs->cme)) {
/* Before detaching the CCs from this class, we need to invalidate the cc
* since we will no longer be marking the cme on their behalf.
*/
for (int i = 0; i < ccs->len; i++) {
const struct rb_callcache *cc = ccs->entries[i].cc;
if (cc->klass == Qundef) continue; // already invalidated
VM_ASSERT(cc->klass == Qundef || vm_cc_check_cme(cc, ccs->cme));
VM_ASSERT(!vm_cc_super_p(cc) && !vm_cc_refinement_p(cc));
vm_cc_invalidate(cc);
}
ruby_xfree(ccs);
return ID_TABLE_DELETE;
}
else {
rb_gc_mark_movable((VALUE)ccs->cme);
for (int i=0; i<ccs->len; i++) {
VM_ASSERT(vm_cc_check_cme(ccs->entries[i].cc, ccs->cme));
for (int i = 0; i < ccs->len; i++) {
const struct rb_callcache *cc = ccs->entries[i].cc;
VM_ASSERT(cc->klass == Qundef || vm_cc_check_cme(cc, ccs->cme));
rb_gc_mark_movable((VALUE)ccs->entries[i].cc);
rb_gc_mark_movable((VALUE)cc);
}
return ID_TABLE_CONTINUE;
}