Optionally traverse non-weak references in rb_gc_vm_weak_table_foreach
For moving garbage collectors, we may want to combine liveliness checking with reference updating for performance. This commit allows for non-weak references to be passed into the callback function when weak_only is false.
This commit is contained in:
parent
c3c7300b89
commit
9e5ff79c5b
Notes:
git
2025-01-27 15:28:55 +00:00
146
gc.c
146
gc.c
@ -3346,22 +3346,39 @@ struct global_vm_table_foreach_data {
|
||||
vm_table_foreach_callback_func callback;
|
||||
vm_table_update_callback_func update_callback;
|
||||
void *data;
|
||||
bool weak_only;
|
||||
};
|
||||
|
||||
static int
|
||||
vm_weak_table_foreach_key(st_data_t key, st_data_t value, st_data_t data, int error)
|
||||
vm_weak_table_foreach_weak_key(st_data_t key, st_data_t value, st_data_t data, int error)
|
||||
{
|
||||
struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
|
||||
|
||||
return iter_data->callback((VALUE)key, iter_data->data);
|
||||
int ret = iter_data->callback((VALUE)key, iter_data->data);
|
||||
|
||||
if (!iter_data->weak_only) {
|
||||
if (ret != ST_CONTINUE) return ret;
|
||||
|
||||
ret = iter_data->callback((VALUE)value, iter_data->data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
vm_weak_table_foreach_update_key(st_data_t *key, st_data_t *value, st_data_t data, int existing)
|
||||
vm_weak_table_foreach_update_weak_key(st_data_t *key, st_data_t *value, st_data_t data, int existing)
|
||||
{
|
||||
struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
|
||||
|
||||
return iter_data->update_callback((VALUE *)key, iter_data->data);
|
||||
int ret = iter_data->update_callback((VALUE *)key, iter_data->data);
|
||||
|
||||
if (!iter_data->weak_only) {
|
||||
if (ret != ST_CONTINUE) return ret;
|
||||
|
||||
ret = iter_data->update_callback((VALUE *)value, iter_data->data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -3369,6 +3386,11 @@ vm_weak_table_str_sym_foreach(st_data_t key, st_data_t value, st_data_t data, in
|
||||
{
|
||||
struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
|
||||
|
||||
if (!iter_data->weak_only) {
|
||||
int ret = iter_data->callback((VALUE)key, iter_data->data);
|
||||
if (ret != ST_CONTINUE) return ret;
|
||||
}
|
||||
|
||||
if (STATIC_SYM_P(value)) {
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
@ -3378,10 +3400,15 @@ vm_weak_table_str_sym_foreach(st_data_t key, st_data_t value, st_data_t data, in
|
||||
}
|
||||
|
||||
static int
|
||||
vm_weak_table_foreach_update_value(st_data_t *key, st_data_t *value, st_data_t data, int existing)
|
||||
vm_weak_table_foreach_update_weak_value(st_data_t *key, st_data_t *value, st_data_t data, int existing)
|
||||
{
|
||||
struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
|
||||
|
||||
if (!iter_data->weak_only) {
|
||||
int ret = iter_data->update_callback((VALUE *)key, iter_data->data);
|
||||
if (ret != ST_CONTINUE) return ret;
|
||||
}
|
||||
|
||||
return iter_data->update_callback((VALUE *)value, iter_data->data);
|
||||
}
|
||||
|
||||
@ -3396,35 +3423,108 @@ free_gen_ivtbl(VALUE obj, struct gen_ivtbl *ivtbl)
|
||||
}
|
||||
|
||||
static int
|
||||
vm_weak_table_gen_ivar_foreach(st_data_t key, st_data_t value, st_data_t data, int error)
|
||||
vm_weak_table_gen_ivar_foreach_too_complex_i(st_data_t _key, st_data_t value, st_data_t data, int error)
|
||||
{
|
||||
int retval = vm_weak_table_foreach_key(key, value, data, error);
|
||||
if (retval == ST_DELETE) {
|
||||
struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
|
||||
|
||||
GC_ASSERT(!iter_data->weak_only);
|
||||
|
||||
return iter_data->callback((VALUE)value, iter_data->data);
|
||||
}
|
||||
|
||||
static int
|
||||
vm_weak_table_gen_ivar_foreach_too_complex_replace_i(st_data_t *_key, st_data_t *value, st_data_t data, int existing)
|
||||
{
|
||||
struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
|
||||
|
||||
GC_ASSERT(!iter_data->weak_only);
|
||||
|
||||
return iter_data->update_callback((VALUE *)value, iter_data->data);
|
||||
}
|
||||
|
||||
struct st_table *rb_generic_ivtbl_get(void);
|
||||
|
||||
static int
|
||||
vm_weak_table_gen_ivar_foreach(st_data_t key, st_data_t value, st_data_t data)
|
||||
{
|
||||
struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
|
||||
|
||||
int ret = iter_data->callback((VALUE)key, iter_data->data);
|
||||
|
||||
switch (ret) {
|
||||
case ST_CONTINUE:
|
||||
break;
|
||||
|
||||
case ST_DELETE:
|
||||
free_gen_ivtbl((VALUE)key, (struct gen_ivtbl *)value);
|
||||
|
||||
FL_UNSET((VALUE)key, FL_EXIVAR);
|
||||
return ST_DELETE;
|
||||
|
||||
case ST_REPLACE: {
|
||||
VALUE new_key = (VALUE)key;
|
||||
ret = iter_data->update_callback(&new_key, iter_data->data);
|
||||
if (key != new_key) ret = ST_DELETE;
|
||||
DURING_GC_COULD_MALLOC_REGION_START();
|
||||
{
|
||||
st_insert(rb_generic_ivtbl_get(), (st_data_t)new_key, value);
|
||||
}
|
||||
DURING_GC_COULD_MALLOC_REGION_END();
|
||||
key = (st_data_t)new_key;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return ret;
|
||||
}
|
||||
return retval;
|
||||
|
||||
if (!iter_data->weak_only) {
|
||||
struct gen_ivtbl *ivtbl = (struct gen_ivtbl *)value;
|
||||
|
||||
if (rb_shape_obj_too_complex((VALUE)key)) {
|
||||
st_foreach_with_replace(
|
||||
ivtbl->as.complex.table,
|
||||
vm_weak_table_gen_ivar_foreach_too_complex_i,
|
||||
vm_weak_table_gen_ivar_foreach_too_complex_replace_i,
|
||||
data
|
||||
);
|
||||
}
|
||||
else {
|
||||
for (uint32_t i = 0; i < ivtbl->as.shape.numiv; i++) {
|
||||
if (SPECIAL_CONST_P(ivtbl->as.shape.ivptr[i])) continue;
|
||||
|
||||
int ivar_ret = iter_data->callback(ivtbl->as.shape.ivptr[i], iter_data->data);
|
||||
switch (ivar_ret) {
|
||||
case ST_CONTINUE:
|
||||
break;
|
||||
case ST_REPLACE:
|
||||
iter_data->update_callback(&ivtbl->as.shape.ivptr[i], iter_data->data);
|
||||
break;
|
||||
default:
|
||||
rb_bug("vm_weak_table_gen_ivar_foreach: return value %d not supported", ivar_ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
vm_weak_table_frozen_strings_foreach(st_data_t key, st_data_t value, st_data_t data, int error)
|
||||
{
|
||||
GC_ASSERT(RB_TYPE_P((VALUE)key, T_STRING));
|
||||
|
||||
int retval = vm_weak_table_foreach_key(key, value, data, error);
|
||||
int retval = vm_weak_table_foreach_weak_key(key, value, data, error);
|
||||
if (retval == ST_DELETE) {
|
||||
FL_UNSET((VALUE)key, RSTRING_FSTR);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
struct st_table *rb_generic_ivtbl_get(void);
|
||||
|
||||
void
|
||||
rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
|
||||
vm_table_update_callback_func update_callback,
|
||||
void *data,
|
||||
bool weak_only,
|
||||
enum rb_gc_vm_weak_tables table)
|
||||
{
|
||||
rb_vm_t *vm = GET_VM();
|
||||
@ -3432,7 +3532,8 @@ rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
|
||||
struct global_vm_table_foreach_data foreach_data = {
|
||||
.callback = callback,
|
||||
.update_callback = update_callback,
|
||||
.data = data
|
||||
.data = data,
|
||||
.weak_only = weak_only,
|
||||
};
|
||||
|
||||
switch (table) {
|
||||
@ -3440,8 +3541,8 @@ rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
|
||||
if (vm->ci_table) {
|
||||
st_foreach_with_replace(
|
||||
vm->ci_table,
|
||||
vm_weak_table_foreach_key,
|
||||
vm_weak_table_foreach_update_key,
|
||||
vm_weak_table_foreach_weak_key,
|
||||
vm_weak_table_foreach_update_weak_key,
|
||||
(st_data_t)&foreach_data
|
||||
);
|
||||
}
|
||||
@ -3451,8 +3552,8 @@ rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
|
||||
if (vm->overloaded_cme_table) {
|
||||
st_foreach_with_replace(
|
||||
vm->overloaded_cme_table,
|
||||
vm_weak_table_foreach_key,
|
||||
vm_weak_table_foreach_update_key,
|
||||
vm_weak_table_foreach_weak_key,
|
||||
vm_weak_table_foreach_update_weak_key,
|
||||
(st_data_t)&foreach_data
|
||||
);
|
||||
}
|
||||
@ -3463,7 +3564,7 @@ rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
|
||||
st_foreach_with_replace(
|
||||
global_symbols.str_sym,
|
||||
vm_weak_table_str_sym_foreach,
|
||||
vm_weak_table_foreach_update_value,
|
||||
vm_weak_table_foreach_update_weak_value,
|
||||
(st_data_t)&foreach_data
|
||||
);
|
||||
}
|
||||
@ -3472,10 +3573,9 @@ rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
|
||||
case RB_GC_VM_GENERIC_IV_TABLE: {
|
||||
st_table *generic_iv_tbl = rb_generic_ivtbl_get();
|
||||
if (generic_iv_tbl) {
|
||||
st_foreach_with_replace(
|
||||
st_foreach(
|
||||
generic_iv_tbl,
|
||||
vm_weak_table_gen_ivar_foreach,
|
||||
vm_weak_table_foreach_update_key,
|
||||
(st_data_t)&foreach_data
|
||||
);
|
||||
}
|
||||
@ -3486,7 +3586,7 @@ rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
|
||||
st_foreach_with_replace(
|
||||
vm->frozen_strings,
|
||||
vm_weak_table_frozen_strings_foreach,
|
||||
vm_weak_table_foreach_update_key,
|
||||
vm_weak_table_foreach_update_weak_key,
|
||||
(st_data_t)&foreach_data
|
||||
);
|
||||
}
|
||||
|
2
gc/gc.h
2
gc/gc.h
@ -77,7 +77,7 @@ void *rb_gc_get_ractor_newobj_cache(void);
|
||||
void rb_gc_initialize_vm_context(struct rb_gc_vm_context *context);
|
||||
void rb_gc_worker_thread_set_vm_context(struct rb_gc_vm_context *context);
|
||||
void rb_gc_worker_thread_unset_vm_context(struct rb_gc_vm_context *context);
|
||||
void rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback, vm_table_update_callback_func update_callback, void *data, enum rb_gc_vm_weak_tables table);
|
||||
void rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback, vm_table_update_callback_func update_callback, void *data, bool weak_only, enum rb_gc_vm_weak_tables table);
|
||||
#endif
|
||||
RUBY_SYMBOL_EXPORT_END
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user