From c78138abd3ccbc80b259430a78dfb6c0f65c6f5c Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 3 Mar 2023 14:19:55 -0500 Subject: Add function rb_data_free This commit adds a function rb_data_free used by obj_free and rb_objspace_call_finalizer to free T_DATA objects. This change also means that RUBY_TYPED_FREE_IMMEDIATELY objects can be freed immediately in rb_objspace_call_finalizer rather than being created into a zombie. --- gc.c | 88 ++++++++++++++++++++++++++++++++------------------------------------ 1 file changed, 42 insertions(+), 46 deletions(-) (limited to 'gc.c') diff --git a/gc.c b/gc.c index 43cbd0f92c..bbb85a21b6 100644 --- a/gc.c +++ b/gc.c @@ -3452,6 +3452,45 @@ obj_free_object_id(rb_objspace_t *objspace, VALUE obj) } } +static bool +rb_data_free(rb_objspace_t *objspace, VALUE obj) +{ + if (DATA_PTR(obj)) { + int free_immediately = false; + void (*dfree)(void *); + void *data = DATA_PTR(obj); + + if (RTYPEDDATA_P(obj)) { + free_immediately = (RANY(obj)->as.typeddata.type->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0; + dfree = RANY(obj)->as.typeddata.type->function.dfree; + } + else { + dfree = RANY(obj)->as.data.dfree; + } + + if (dfree) { + if (dfree == RUBY_DEFAULT_FREE) { + xfree(data); + RB_DEBUG_COUNTER_INC(obj_data_xfree); + } + else if (free_immediately) { + (*dfree)(data); + RB_DEBUG_COUNTER_INC(obj_data_imm_free); + } + else { + RB_DEBUG_COUNTER_INC(obj_data_zombie); + make_zombie(objspace, obj, dfree, data); + return false; + } + } + else { + RB_DEBUG_COUNTER_INC(obj_data_empty); + } + } + + return true; +} + static int obj_free(rb_objspace_t *objspace, VALUE obj) { @@ -3608,42 +3647,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj) } break; case T_DATA: - if (DATA_PTR(obj)) { - int free_immediately = FALSE; - void (*dfree)(void *); - void *data = DATA_PTR(obj); - - if (RTYPEDDATA_P(obj)) { - free_immediately = (RANY(obj)->as.typeddata.type->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0; - dfree = RANY(obj)->as.typeddata.type->function.dfree; - if (0 && free_immediately == 0) { - /* to expose non-free-immediate T_DATA */ - fprintf(stderr, "not immediate -> %s\n", RANY(obj)->as.typeddata.type->wrap_struct_name); - } - } - else { - dfree = RANY(obj)->as.data.dfree; - } - - if (dfree) { - if (dfree == RUBY_DEFAULT_FREE) { - xfree(data); - RB_DEBUG_COUNTER_INC(obj_data_xfree); - } - else if (free_immediately) { - (*dfree)(data); - RB_DEBUG_COUNTER_INC(obj_data_imm_free); - } - else { - make_zombie(objspace, obj, dfree, data); - RB_DEBUG_COUNTER_INC(obj_data_zombie); - return FALSE; - } - } - else { - RB_DEBUG_COUNTER_INC(obj_data_empty); - } - } + if (!rb_data_free(objspace, obj)) return false; break; case T_MATCH: if (RANY(obj)->as.match.rmatch) { @@ -4582,16 +4586,8 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace) if (rb_obj_is_mutex(vp)) break; if (rb_obj_is_fiber(vp)) break; if (rb_obj_is_main_ractor(vp)) break; - if (RTYPEDDATA_P(vp)) { - RDATA(p)->dfree = RANY(p)->as.typeddata.type->function.dfree; - } - RANY(p)->as.free.flags = 0; - if (RANY(p)->as.data.dfree == RUBY_DEFAULT_FREE) { - xfree(DATA_PTR(p)); - } - else if (RANY(p)->as.data.dfree) { - make_zombie(objspace, vp, RANY(p)->as.data.dfree, RANY(p)->as.data.data); - } + + rb_data_free(objspace, vp); break; case T_FILE: if (RANY(p)->as.file.fptr) { -- cgit v1.2.3