Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions internal/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
48 changes: 25 additions & 23 deletions iseq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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();
}
}
}
Expand Down