зеркало из https://github.com/github/ruby.git
make `overloaded_cme_table` truly weak key map
`overloaded_cme_table` keeps cme -> monly_cme pairs to manage corresponding `monly_cme` for `cme`. The lifetime of the `monly_cme` should be longer than `monly_cme`, but the previous patch losts the reference to the living `monly_cme`. Now `overloaded_cme_table` values are always root (keys are only weak reference), it means `monly_cme` does not freed until corresponding `cme` is invalidated. To make managing easy, move `overloaded_cme_table` to `rb_vm_t`.
This commit is contained in:
Родитель
3c7e95966d
Коммит
ad450c9fe5
8
gc.c
8
gc.c
|
@ -6379,9 +6379,7 @@ mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
|
|||
if (def->body.iseq.iseqptr) gc_mark(objspace, (VALUE)def->body.iseq.iseqptr);
|
||||
gc_mark(objspace, (VALUE)def->body.iseq.cref);
|
||||
if (def->iseq_overload && me->defined_class) { // cme
|
||||
const rb_callable_method_entry_t *monly_cme = rb_vm_lookup_overloaded_cme((const rb_callable_method_entry_t *)me);
|
||||
if (monly_cme) {
|
||||
gc_mark(objspace, (VALUE)monly_cme);
|
||||
if (rb_vm_lookup_overloaded_cme((const rb_callable_method_entry_t *)me)) {
|
||||
gc_mark_and_pin(objspace, (VALUE)me);
|
||||
}
|
||||
}
|
||||
|
@ -10113,9 +10111,6 @@ gc_ref_update(void *vstart, void *vend, size_t stride, rb_objspace_t * objspace,
|
|||
extern rb_symbols_t ruby_global_symbols;
|
||||
#define global_symbols ruby_global_symbols
|
||||
|
||||
|
||||
st_table *rb_vm_overloaded_cme_table(void);
|
||||
|
||||
static void
|
||||
gc_update_references(rb_objspace_t *objspace)
|
||||
{
|
||||
|
@ -10151,7 +10146,6 @@ gc_update_references(rb_objspace_t *objspace)
|
|||
gc_update_table_refs(objspace, objspace->id_to_obj_tbl);
|
||||
gc_update_table_refs(objspace, global_symbols.str_sym);
|
||||
gc_update_table_refs(objspace, finalizer_table);
|
||||
gc_update_table_refs(objspace, rb_vm_overloaded_cme_table());
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
|
6
vm.c
6
vm.c
|
@ -2540,6 +2540,8 @@ rb_vm_update_references(void *ptr)
|
|||
vm->top_self = rb_gc_location(vm->top_self);
|
||||
vm->orig_progname = rb_gc_location(vm->orig_progname);
|
||||
|
||||
rb_gc_update_tbl_refs(vm->overloaded_cme_table);
|
||||
|
||||
if (vm->coverages) {
|
||||
vm->coverages = rb_gc_location(vm->coverages);
|
||||
vm->me2counter = rb_gc_location(vm->me2counter);
|
||||
|
@ -2637,9 +2639,10 @@ rb_vm_mark(void *ptr)
|
|||
rb_mark_tbl(vm->loading_table);
|
||||
}
|
||||
|
||||
rb_gc_mark_values(RUBY_NSIG, vm->trap_list.cmd);
|
||||
rb_gc_mark_values(RUBY_NSIG, vm->trap_list.cmd);
|
||||
|
||||
rb_id_table_foreach_values(vm->negative_cme_table, vm_mark_negative_cme, NULL);
|
||||
rb_mark_tbl_no_pin(vm->overloaded_cme_table);
|
||||
for (i=0; i<VM_GLOBAL_CC_CACHE_TABLE_SIZE; i++) {
|
||||
const struct rb_callcache *cc = vm->global_cc_cache_table[i];
|
||||
|
||||
|
@ -3801,6 +3804,7 @@ Init_BareVM(void)
|
|||
vm->objspace = rb_objspace_alloc();
|
||||
ruby_current_vm_ptr = vm;
|
||||
vm->negative_cme_table = rb_id_table_create(16);
|
||||
vm->overloaded_cme_table = st_init_numtable();
|
||||
|
||||
Init_native_thread(th);
|
||||
th->vm = vm;
|
||||
|
|
|
@ -714,6 +714,7 @@ typedef struct rb_vm_struct {
|
|||
int builtin_inline_index;
|
||||
|
||||
struct rb_id_table *negative_cme_table;
|
||||
st_table *overloaded_cme_table; // cme -> overloaded_cme
|
||||
|
||||
#ifndef VM_GLOBAL_CC_CACHE_TABLE_SIZE
|
||||
#define VM_GLOBAL_CC_CACHE_TABLE_SIZE 1023
|
||||
|
|
38
vm_method.c
38
vm_method.c
|
@ -150,7 +150,7 @@ static rb_method_entry_t *rb_method_entry_alloc(ID called_id, VALUE owner, VALUE
|
|||
const rb_method_entry_t * rb_method_entry_clone(const rb_method_entry_t *src_me);
|
||||
static const rb_callable_method_entry_t *complemented_callable_method_entry(VALUE klass, ID id);
|
||||
static const rb_callable_method_entry_t *lookup_overloaded_cme(const rb_callable_method_entry_t *cme);
|
||||
static void delete_overloaded_cme(const rb_callable_method_entry_t *cme);
|
||||
|
||||
|
||||
static void
|
||||
clear_method_cache_by_id_in_class(VALUE klass, ID mid)
|
||||
|
@ -216,7 +216,6 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid)
|
|||
rb_callable_method_entry_t *monly_cme = (rb_callable_method_entry_t *)lookup_overloaded_cme(cme);
|
||||
if (monly_cme) {
|
||||
vm_cme_invalidate(monly_cme);
|
||||
delete_overloaded_cme(monly_cme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -393,6 +392,8 @@ rb_method_definition_release(rb_method_definition_t *def, int complemented)
|
|||
}
|
||||
}
|
||||
|
||||
static void delete_overloaded_cme(const rb_callable_method_entry_t *cme);
|
||||
|
||||
void
|
||||
rb_free_method_entry(const rb_method_entry_t *me)
|
||||
{
|
||||
|
@ -922,12 +923,12 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil
|
|||
}
|
||||
|
||||
static rb_method_entry_t *rb_method_entry_alloc(ID called_id, VALUE owner, VALUE defined_class, const rb_method_definition_t *def);
|
||||
static st_table *overloaded_cme_table;
|
||||
|
||||
st_table *
|
||||
rb_vm_overloaded_cme_table(void)
|
||||
static st_table *
|
||||
overloaded_cme_table(void)
|
||||
{
|
||||
return overloaded_cme_table;
|
||||
VM_ASSERT(GET_VM()->overloaded_cme_table != NULL);
|
||||
return GET_VM()->overloaded_cme_table;
|
||||
}
|
||||
|
||||
#if VM_CHECK_MODE > 0
|
||||
|
@ -943,7 +944,7 @@ void
|
|||
rb_vm_dump_overloaded_cme_table(void)
|
||||
{
|
||||
fprintf(stderr, "== rb_vm_dump_overloaded_cme_table\n");
|
||||
st_foreach(overloaded_cme_table, vm_dump_overloaded_cme_table, 0);
|
||||
st_foreach(overloaded_cme_table(), vm_dump_overloaded_cme_table, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -956,10 +957,7 @@ lookup_overloaded_cme_i(st_data_t *key, st_data_t *value, st_data_t data, int ex
|
|||
const rb_callable_method_entry_t **ptr = (const rb_callable_method_entry_t **)data;
|
||||
|
||||
if (rb_objspace_garbage_object_p((VALUE)cme) ||
|
||||
rb_objspace_garbage_object_p((VALUE)monly_cme) ||
|
||||
METHOD_ENTRY_INVALIDATED(cme) ||
|
||||
METHOD_ENTRY_INVALIDATED(monly_cme)) {
|
||||
|
||||
rb_objspace_garbage_object_p((VALUE)monly_cme)) {
|
||||
*ptr = NULL;
|
||||
return ST_DELETE;
|
||||
}
|
||||
|
@ -977,14 +975,8 @@ lookup_overloaded_cme(const rb_callable_method_entry_t *cme)
|
|||
ASSERT_vm_locking();
|
||||
|
||||
const rb_callable_method_entry_t *monly_cme = NULL;
|
||||
st_update(overloaded_cme_table, (st_data_t)cme, lookup_overloaded_cme_i, (st_data_t)&monly_cme);
|
||||
|
||||
if (monly_cme) {
|
||||
return monly_cme;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
st_update(overloaded_cme_table(), (st_data_t)cme, lookup_overloaded_cme_i, (st_data_t)&monly_cme);
|
||||
return monly_cme;
|
||||
}
|
||||
|
||||
// used by gc.c
|
||||
|
@ -998,7 +990,7 @@ static void
|
|||
delete_overloaded_cme(const rb_callable_method_entry_t *cme)
|
||||
{
|
||||
ASSERT_vm_locking();
|
||||
st_delete(overloaded_cme_table, (st_data_t *)&cme, NULL);
|
||||
st_delete(overloaded_cme_table(), (st_data_t *)&cme, NULL);
|
||||
}
|
||||
|
||||
static const rb_callable_method_entry_t *
|
||||
|
@ -1006,7 +998,7 @@ get_overloaded_cme(const rb_callable_method_entry_t *cme)
|
|||
{
|
||||
const rb_callable_method_entry_t *monly_cme = lookup_overloaded_cme(cme);
|
||||
|
||||
if (monly_cme) {
|
||||
if (monly_cme && !METHOD_ENTRY_INVALIDATED(monly_cme)) {
|
||||
return monly_cme;
|
||||
}
|
||||
else {
|
||||
|
@ -1021,7 +1013,7 @@ get_overloaded_cme(const rb_callable_method_entry_t *cme)
|
|||
def);
|
||||
|
||||
ASSERT_vm_locking();
|
||||
st_insert(overloaded_cme_table, (st_data_t)cme, (st_data_t)me);
|
||||
st_insert(overloaded_cme_table(), (st_data_t)cme, (st_data_t)me);
|
||||
|
||||
METHOD_ENTRY_VISI_SET(me, METHOD_ENTRY_VISI(cme));
|
||||
return (rb_callable_method_entry_t *)me;
|
||||
|
@ -2828,7 +2820,7 @@ obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
|
|||
void
|
||||
Init_Method(void)
|
||||
{
|
||||
overloaded_cme_table = st_init_numtable();
|
||||
//
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Загрузка…
Ссылка в новой задаче