diff --git a/cont.c b/cont.c index 463be7400f..8af093a316 100644 --- a/cont.c +++ b/cont.c @@ -48,8 +48,8 @@ static const int DEBUG = 0; #define RB_PAGE_MASK (~(RB_PAGE_SIZE - 1)) static long pagesize; -const rb_data_type_t rb_cont_data_type; -const rb_data_type_t rb_fiber_data_type; +static const rb_data_type_t rb_cont_data_type; +static const rb_data_type_t rb_fiber_data_type; static VALUE rb_cContinuation; static VALUE rb_cFiber; static VALUE rb_eFiberError; @@ -1239,17 +1239,11 @@ cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont) asan_unpoison_memory_region(cont->machine.stack_src, size, false); MEMCPY(cont->machine.stack, cont->machine.stack_src, VALUE, size); } -const rb_data_type_t rb_cont_data_type = { - "continuation", - {cont_mark, cont_free, cont_memsize, cont_compact}, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY -}; -void -rb_cont_handle_weak_references(VALUE obj) +static void +cont_handle_weak_references(void *ptr) { - rb_context_t *cont; - TypedData_Get_Struct(obj, rb_context_t, &rb_cont_data_type, cont); + rb_context_t *cont = ptr; if (!cont) return; @@ -1260,6 +1254,12 @@ rb_cont_handle_weak_references(VALUE obj) } } +static const rb_data_type_t rb_cont_data_type = { + "continuation", + {cont_mark, cont_free, cont_memsize, cont_compact, cont_handle_weak_references}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + static inline void cont_save_thread(rb_context_t *cont, rb_thread_t *th) { @@ -1996,17 +1996,10 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval) * */ -const rb_data_type_t rb_fiber_data_type = { - "fiber", - {fiber_mark, fiber_free, fiber_memsize, fiber_compact,}, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY -}; - -void -rb_fiber_handle_weak_references(VALUE obj) +static void +fiber_handle_weak_references(void *ptr) { - rb_fiber_t *fiber; - TypedData_Get_Struct(obj, rb_fiber_t, &rb_fiber_data_type, fiber); + rb_fiber_t *fiber = ptr; if (!fiber) return; @@ -2017,6 +2010,12 @@ rb_fiber_handle_weak_references(VALUE obj) } } +static const rb_data_type_t rb_fiber_data_type = { + "fiber", + {fiber_mark, fiber_free, fiber_memsize, fiber_compact, fiber_handle_weak_references}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + static VALUE fiber_alloc(VALUE klass) { diff --git a/gc.c b/gc.c index 98e5712ca4..c47f68c50c 100644 --- a/gc.c +++ b/gc.c @@ -1204,17 +1204,6 @@ rb_gc_handle_weak_references_alive_p(VALUE obj) return rb_gc_impl_handle_weak_references_alive_p(rb_gc_get_objspace(), obj); } -extern const rb_data_type_t rb_weakmap_type; -void rb_wmap_handle_weak_references(VALUE obj); -extern const rb_data_type_t rb_weakkeymap_type; -void rb_wkmap_handle_weak_references(VALUE obj); - -extern const rb_data_type_t rb_fiber_data_type; -void rb_fiber_handle_weak_references(VALUE obj); - -extern const rb_data_type_t rb_cont_data_type; -void rb_cont_handle_weak_references(VALUE obj); - void rb_gc_handle_weak_references(VALUE obj) { @@ -1223,20 +1212,14 @@ rb_gc_handle_weak_references(VALUE obj) if (RTYPEDDATA_P(obj)) { const rb_data_type_t *type = RTYPEDDATA_TYPE(obj); - if (type == &rb_fiber_data_type) { - rb_fiber_handle_weak_references(obj); - } - else if (type == &rb_cont_data_type) { - rb_cont_handle_weak_references(obj); - } - else if (type == &rb_weakmap_type) { - rb_wmap_handle_weak_references(obj); - } - else if (type == &rb_weakkeymap_type) { - rb_wkmap_handle_weak_references(obj); + if (type->function.handle_weak_references) { + (type->function.handle_weak_references)(RTYPEDDATA_GET_DATA(obj)); } else { - rb_bug("rb_gc_handle_weak_references: unknown TypedData %s", RTYPEDDATA_TYPE(obj)->wrap_struct_name); + rb_bug( + "rb_gc_handle_weak_references: TypedData %s does not implement handle_weak_references", + RTYPEDDATA_TYPE(obj)->wrap_struct_name + ); } } else { diff --git a/include/ruby/internal/core/rtypeddata.h b/include/ruby/internal/core/rtypeddata.h index aadccc238b..bf6423f8d2 100644 --- a/include/ruby/internal/core/rtypeddata.h +++ b/include/ruby/internal/core/rtypeddata.h @@ -262,11 +262,9 @@ struct rb_data_type_struct { RUBY_DATA_FUNC dcompact; /** - * This field is reserved for future extension. For now, it must be - * filled with zeros. + * @internal */ - void *reserved[1]; /* For future extension. - This array *must* be filled with ZERO. */ + void (*handle_weak_references)(void *); } function; /** diff --git a/weakmap.c b/weakmap.c index 7b6f27ce2b..b027604f5e 100644 --- a/weakmap.c +++ b/weakmap.c @@ -112,6 +112,26 @@ wmap_compact(void *ptr) } } +static int +rb_wmap_handle_weak_references_i(st_data_t key, st_data_t val, st_data_t arg) +{ + if (rb_gc_handle_weak_references_alive_p(key) && + rb_gc_handle_weak_references_alive_p(val)) { + return ST_CONTINUE; + } + else { + return ST_DELETE; + } +} + +static void +wmap_handle_weak_references(void *ptr) +{ + struct weakmap *w = ptr; + + st_foreach(w->table, rb_wmap_handle_weak_references_i, (st_data_t)0); +} + const rb_data_type_t rb_weakmap_type = { "weakmap", { @@ -119,6 +139,7 @@ const rb_data_type_t rb_weakmap_type = { wmap_free, wmap_memsize, wmap_compact, + wmap_handle_weak_references, }, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE }; @@ -140,27 +161,6 @@ static const struct st_hash_type wmap_hash_type = { wmap_hash, }; -static int -rb_wmap_handle_weak_references_i(st_data_t key, st_data_t val, st_data_t arg) -{ - if (rb_gc_handle_weak_references_alive_p(key) && - rb_gc_handle_weak_references_alive_p(val)) { - return ST_CONTINUE; - } - else { - return ST_DELETE; - } -} - -void -rb_wmap_handle_weak_references(VALUE self) -{ - struct weakmap *w; - TypedData_Get_Struct(self, struct weakmap, &rb_weakmap_type, w); - - st_foreach(w->table, rb_wmap_handle_weak_references_i, (st_data_t)0); -} - static VALUE wmap_allocate(VALUE klass) { @@ -588,13 +588,33 @@ wkmap_compact(void *ptr) } } -const rb_data_type_t rb_weakkeymap_type = { +static int +rb_wkmap_handle_weak_references_i(st_data_t key, st_data_t val, st_data_t arg) +{ + if (rb_gc_handle_weak_references_alive_p(key)) { + return ST_CONTINUE; + } + else { + return ST_DELETE; + } +} + +static void +wkmap_handle_weak_references(void *ptr) +{ + struct weakkeymap *w = ptr; + + st_foreach(w->table, rb_wkmap_handle_weak_references_i, (st_data_t)0); +} + +static const rb_data_type_t rb_weakkeymap_type = { "weakkeymap", { wkmap_mark, wkmap_free, wkmap_memsize, wkmap_compact, + wkmap_handle_weak_references, }, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE }; @@ -621,26 +641,6 @@ static const struct st_hash_type wkmap_hash_type = { wkmap_hash, }; -static int -rb_wkmap_handle_weak_references_i(st_data_t key, st_data_t val, st_data_t arg) -{ - if (rb_gc_handle_weak_references_alive_p(key)) { - return ST_CONTINUE; - } - else { - return ST_DELETE; - } -} - -void -rb_wkmap_handle_weak_references(VALUE self) -{ - struct weakkeymap *w; - TypedData_Get_Struct(self, struct weakkeymap, &rb_weakkeymap_type, w); - - st_foreach(w->table, rb_wkmap_handle_weak_references_i, (st_data_t)0); -} - static VALUE wkmap_allocate(VALUE klass) {