Skip to content

Commit 8eab317

Browse files
committed
Convert cc_refinement_table into TypedData object
This converts the cc_refinement_table in the VM into a standard TypedData object using rb_gc_declare_weak_references to allow it to be . This allows us to store all the refinements in a flat array, and simply remove them as that are GC'd, we don't need a set for efficient deletes. This should also allow us to assume that imemo_callcache never requires additional cleanup.
1 parent 64fdfb7 commit 8eab317

File tree

6 files changed

+102
-88
lines changed

6 files changed

+102
-88
lines changed

gc.c

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,15 +2270,6 @@ rb_gc_obj_free_vm_weak_references(VALUE obj)
22702270
break;
22712271
case T_IMEMO:
22722272
switch (imemo_type(obj)) {
2273-
case imemo_callcache: {
2274-
const struct rb_callcache *cc = (const struct rb_callcache *)obj;
2275-
2276-
if (vm_cc_refinement_p(cc)) {
2277-
rb_vm_delete_cc_refinement(cc);
2278-
}
2279-
2280-
break;
2281-
}
22822273
case imemo_callinfo:
22832274
rb_vm_ci_free((const struct rb_callinfo *)obj);
22842275
break;
@@ -4062,23 +4053,6 @@ vm_weak_table_foreach_update_weak_key(st_data_t *key, st_data_t *value, st_data_
40624053
return ret;
40634054
}
40644055

4065-
static int
4066-
vm_weak_table_cc_refinement_foreach(st_data_t key, st_data_t data, int error)
4067-
{
4068-
struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
4069-
4070-
return iter_data->callback((VALUE)key, iter_data->data);
4071-
}
4072-
4073-
static int
4074-
vm_weak_table_cc_refinement_foreach_update_update(st_data_t *key, st_data_t data, int existing)
4075-
{
4076-
struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
4077-
4078-
return iter_data->update_callback((VALUE *)key, iter_data->data);
4079-
}
4080-
4081-
40824056
static int
40834057
vm_weak_table_sym_set_foreach(VALUE *sym_ptr, void *data)
40844058
{
@@ -4275,17 +4249,6 @@ rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
42754249
);
42764250
break;
42774251
}
4278-
case RB_GC_VM_CC_REFINEMENT_TABLE: {
4279-
if (vm->cc_refinement_table) {
4280-
set_foreach_with_replace(
4281-
vm->cc_refinement_table,
4282-
vm_weak_table_cc_refinement_foreach,
4283-
vm_weak_table_cc_refinement_foreach_update_update,
4284-
(st_data_t)&foreach_data
4285-
);
4286-
}
4287-
break;
4288-
}
42894252
case RB_GC_VM_WEAK_TABLE_COUNT:
42904253
rb_bug("Unreachable");
42914254
default:

gc/gc.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ enum rb_gc_vm_weak_tables {
3131
RB_GC_VM_ID2REF_TABLE,
3232
RB_GC_VM_GENERIC_FIELDS_TABLE,
3333
RB_GC_VM_FROZEN_STRINGS_TABLE,
34-
RB_GC_VM_CC_REFINEMENT_TABLE,
3534
RB_GC_VM_WEAK_TABLE_COUNT
3635
};
3736

method.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,6 @@ void rb_scope_visibility_set(rb_method_visibility_t);
264264
VALUE rb_unnamed_parameters(int arity);
265265

266266
void rb_vm_insert_cc_refinement(const struct rb_callcache *cc);
267-
void rb_vm_delete_cc_refinement(const struct rb_callcache *cc);
268267

269268
void rb_clear_method_cache(VALUE klass_or_module, ID mid);
270269
void rb_clear_all_refinement_method_cache(void);

vm.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3236,6 +3236,7 @@ rb_vm_update_references(void *ptr)
32363236
vm->self = rb_gc_location(vm->self);
32373237
vm->mark_object_ary = rb_gc_location(vm->mark_object_ary);
32383238
vm->orig_progname = rb_gc_location(vm->orig_progname);
3239+
vm->cc_refinement_set = rb_gc_location(vm->cc_refinement_set);
32393240

32403241
if (vm->root_box)
32413242
rb_box_gc_update_references(vm->root_box);
@@ -3324,6 +3325,7 @@ rb_vm_mark(void *ptr)
33243325
rb_gc_mark_movable(vm->orig_progname);
33253326
rb_gc_mark_movable(vm->coverages);
33263327
rb_gc_mark_movable(vm->me2counter);
3328+
rb_gc_mark_movable(vm->cc_refinement_set);
33273329

33283330
rb_gc_mark_values(RUBY_NSIG, vm->trap_list.cmd);
33293331

@@ -3414,10 +3416,6 @@ ruby_vm_destruct(rb_vm_t *vm)
34143416
st_free_table(vm->ci_table);
34153417
vm->ci_table = NULL;
34163418
}
3417-
if (vm->cc_refinement_table) {
3418-
rb_set_free_table(vm->cc_refinement_table);
3419-
vm->cc_refinement_table = NULL;
3420-
}
34213419
RB_ALTSTACK_FREE(vm->main_altstack);
34223420

34233421
struct global_object_list *next;
@@ -3510,7 +3508,6 @@ vm_memsize(const void *ptr)
35103508
vm_memsize_builtin_function_table(vm->builtin_function_table) +
35113509
rb_id_table_memsize(vm->negative_cme_table) +
35123510
rb_st_memsize(vm->overloaded_cme_table) +
3513-
rb_set_memsize(vm->cc_refinement_table) +
35143511
vm_memsize_constant_cache()
35153512
);
35163513

@@ -4736,6 +4733,8 @@ rb_vm_register_global_object(VALUE obj)
47364733
}
47374734
}
47384735

4736+
VALUE rb_cc_refinement_set_create(void);
4737+
47394738
void
47404739
Init_vm_objects(void)
47414740
{
@@ -4744,7 +4743,7 @@ Init_vm_objects(void)
47444743
/* initialize mark object array, hash */
47454744
vm->mark_object_ary = pin_array_list_new(Qnil);
47464745
vm->ci_table = st_init_table(&vm_ci_hashtype);
4747-
vm->cc_refinement_table = rb_set_init_numtable();
4746+
vm->cc_refinement_set = rb_cc_refinement_set_create();
47484747
}
47494748

47504749
// Whether JIT is enabled or not, we need to load/undef `#with_jit` for other builtins.

vm_core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ typedef struct rb_vm_struct {
816816
struct rb_id_table *negative_cme_table;
817817
st_table *overloaded_cme_table; // cme -> overloaded_cme
818818
set_table *unused_block_warning_table;
819-
set_table *cc_refinement_table;
819+
VALUE cc_refinement_set;
820820

821821
// This id table contains a mapping from ID to ICs. It does this with ID
822822
// keys and nested st_tables as values. The nested tables have ICs as keys

vm_method.c

Lines changed: 96 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -587,32 +587,6 @@ rb_invalidate_method_caches(struct rb_id_table *cm_tbl, VALUE cc_tbl)
587587
}
588588
}
589589

590-
static int
591-
invalidate_cc_refinement(st_data_t key, st_data_t data)
592-
{
593-
VALUE v = (VALUE)key;
594-
void *ptr = rb_asan_poisoned_object_p(v);
595-
rb_asan_unpoison_object(v, false);
596-
597-
if (rb_gc_pointer_to_heap_p(v) &&
598-
!rb_objspace_garbage_object_p(v) &&
599-
RBASIC(v)->flags) { // liveness check
600-
const struct rb_callcache *cc = (const struct rb_callcache *)v;
601-
602-
VM_ASSERT(vm_cc_refinement_p(cc));
603-
604-
if (vm_cc_valid(cc)) {
605-
vm_cc_invalidate(cc);
606-
}
607-
}
608-
609-
if (ptr) {
610-
rb_asan_poison_object(v);
611-
}
612-
613-
return ST_CONTINUE;
614-
}
615-
616590
static st_index_t
617591
vm_ci_hash(VALUE v)
618592
{
@@ -722,28 +696,94 @@ rb_vm_ci_free(const struct rb_callinfo *ci)
722696
st_delete(vm->ci_table, &key, NULL);
723697
}
724698

725-
void
726-
rb_vm_insert_cc_refinement(const struct rb_callcache *cc)
699+
struct cc_refinement_entries {
700+
VALUE *entries;
701+
size_t len;
702+
size_t capa;
703+
};
704+
705+
static void
706+
cc_refinement_set_free(void *ptr)
727707
{
728-
st_data_t key = (st_data_t)cc;
708+
struct cc_refinement_entries *e = ptr;
709+
xfree(e->entries);
710+
}
729711

730-
rb_vm_t *vm = GET_VM();
731-
RB_VM_LOCK_ENTER();
732-
{
733-
rb_set_insert(vm->cc_refinement_table, key);
712+
static size_t
713+
cc_refinement_set_memsize(const void *ptr)
714+
{
715+
const struct cc_refinement_entries *e = ptr;
716+
return e->capa * sizeof(VALUE);
717+
}
718+
719+
static void
720+
cc_refinement_set_compact(void *ptr)
721+
{
722+
struct cc_refinement_entries *e = ptr;
723+
for (size_t i = 0; i < e->len; i++) {
724+
e->entries[i] = rb_gc_location(e->entries[i]);
734725
}
735-
RB_VM_LOCK_LEAVE();
736726
}
737727

738-
void
739-
rb_vm_delete_cc_refinement(const struct rb_callcache *cc)
728+
static void
729+
cc_refinement_set_handle_weak_references(void *ptr)
740730
{
741-
ASSERT_vm_locking();
731+
struct cc_refinement_entries *e = ptr;
732+
size_t write = 0;
733+
for (size_t read = 0; read < e->len; read++) {
734+
if (rb_gc_handle_weak_references_alive_p(e->entries[read])) {
735+
e->entries[write++] = e->entries[read];
736+
}
737+
}
738+
e->len = write;
739+
}
740+
741+
static const rb_data_type_t cc_refinement_set_type = {
742+
"VM/cc_refinement_set",
743+
{
744+
NULL,
745+
cc_refinement_set_free,
746+
cc_refinement_set_memsize,
747+
cc_refinement_set_compact,
748+
cc_refinement_set_handle_weak_references,
749+
},
750+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
751+
};
752+
753+
VALUE
754+
rb_cc_refinement_set_create(void)
755+
{
756+
struct cc_refinement_entries *e;
757+
VALUE obj = TypedData_Make_Struct(0, struct cc_refinement_entries, &cc_refinement_set_type, e);
758+
759+
e->entries = NULL;
760+
e->len = 0;
761+
e->capa = 0;
762+
763+
rb_gc_declare_weak_references(obj);
764+
765+
return obj;
766+
}
742767

768+
void
769+
rb_vm_insert_cc_refinement(const struct rb_callcache *cc)
770+
{
743771
rb_vm_t *vm = GET_VM();
744-
st_data_t key = (st_data_t)cc;
772+
RB_VM_LOCK_ENTER();
773+
{
774+
struct cc_refinement_entries *e = RTYPEDDATA_GET_DATA(vm->cc_refinement_set);
775+
if (e->len == e->capa) {
776+
size_t new_capa = e->capa == 0 ? 16 : e->capa * 2;
777+
SIZED_REALLOC_N(e->entries, VALUE, new_capa, e->capa);
778+
e->capa = new_capa;
779+
}
780+
e->entries[e->len++] = (VALUE)cc;
745781

746-
rb_set_table_delete(vm->cc_refinement_table, &key);
782+
// We never mark the cc, but we need to issue a writebarrier so that
783+
// the refinement set can be added to the remembered set
784+
RB_OBJ_WRITTEN(vm->cc_refinement_set, Qundef, (VALUE)cc);
785+
}
786+
RB_VM_LOCK_LEAVE();
747787
}
748788

749789
void
@@ -753,9 +793,23 @@ rb_clear_all_refinement_method_cache(void)
753793

754794
RB_VM_LOCK_ENTER();
755795
{
756-
rb_set_table_foreach(vm->cc_refinement_table, invalidate_cc_refinement, (st_data_t)NULL);
757-
rb_set_table_clear(vm->cc_refinement_table);
758-
rb_set_compact_table(vm->cc_refinement_table);
796+
struct cc_refinement_entries *e = RTYPEDDATA_GET_DATA(vm->cc_refinement_set);
797+
for (size_t i = 0; i < e->len; i++) {
798+
VALUE v = e->entries[i];
799+
800+
// All objects should be live as weak references are pruned in
801+
// cc_refinement_set_handle_weak_references
802+
VM_ASSERT(rb_gc_pointer_to_heap_p(v));
803+
VM_ASSERT(!rb_objspace_garbage_object_p(v));
804+
805+
const struct rb_callcache *cc = (const struct rb_callcache *)v;
806+
VM_ASSERT(vm_cc_refinement_p(cc));
807+
808+
if (vm_cc_valid(cc)) {
809+
vm_cc_invalidate(cc);
810+
}
811+
}
812+
e->len = 0;
759813
}
760814
RB_VM_LOCK_LEAVE();
761815

0 commit comments

Comments
 (0)