diff --git a/internal/gc.h b/internal/gc.h index a8742fc948475d..d0bbc033882d17 100644 --- a/internal/gc.h +++ b/internal/gc.h @@ -226,11 +226,6 @@ void rb_gc_after_fork(rb_pid_t pid); if (_obj != (VALUE)*(ptr)) *(ptr) = (void *)_obj; \ } while (0) -#define rb_gc_move_ptr(ptr) do { \ - VALUE _obj = rb_gc_location((VALUE)*(ptr)); \ - if (_obj != (VALUE)*(ptr)) *(ptr) = (void *)_obj; \ -} while (0) - RUBY_SYMBOL_EXPORT_BEGIN /* exports for objspace module */ void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data); diff --git a/iseq.c b/iseq.c index 6f0d5a0f5eea43..c418e1786988b9 100644 --- a/iseq.c +++ b/iseq.c @@ -340,12 +340,28 @@ rb_iseq_mark_and_move_each_body_value(const rb_iseq_t *iseq, VALUE *original_ise } static bool -cc_is_active(const struct rb_callcache *cc) +cc_is_active(const struct rb_callcache *cc, bool reference_updating) { - RUBY_ASSERT(cc); - RUBY_ASSERT(vm_cc_markable(cc)); + if (cc) { + if (cc == rb_vm_empty_cc() || rb_vm_empty_cc_for_super()) { + return false; + } + + if (reference_updating) { + cc = (const struct rb_callcache *)rb_gc_location((VALUE)cc); + } - return vm_cc_valid(cc) && !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)); + if (vm_cc_markable(cc) && vm_cc_valid(cc)) { + const struct rb_callable_method_entry_struct *cme = vm_cc_cme(cc); + if (reference_updating) { + cme = (const struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cme); + } + if (!METHOD_ENTRY_INVALIDATED(cme)) { + return true; + } + } + } + return false; } void @@ -369,30 +385,16 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating) if (body->mandatory_only_iseq) rb_gc_mark_and_move_ptr(&body->mandatory_only_iseq); if (body->call_data) { - struct rb_call_data *cds = body->call_data; for (unsigned int i = 0; i < body->ci_size; i++) { + struct rb_call_data *cds = body->call_data; if (cds[i].ci) rb_gc_mark_and_move_ptr(&cds[i].ci); - const struct rb_callcache *cc = cds[i].cc; - if (!cc || cc == rb_vm_empty_cc() || cc == rb_vm_empty_cc_for_super()) { - // No need for marking, reference updating, or clearing - // We also want to avoid reassigning to improve CoW - continue; - } - - if (reference_updating) { - rb_gc_move_ptr(&cds[i].cc); + if (cc_is_active(cds[i].cc, reference_updating)) { + rb_gc_mark_and_move_ptr(&cds[i].cc); } - else { - if (cc_is_active(cc)) { - rb_gc_mark_movable((VALUE)cc); - } - else { - // Either the CC or CME has been invalidated. Replace - // it with the empty CC so that it can be GC'd. - cds[i].cc = rb_vm_empty_cc(); - } + else if (cds[i].cc != rb_vm_empty_cc()) { + cds[i].cc = rb_vm_empty_cc(); } } }