diff options
| author | Peter Zhu <peter@peterzhu.ca> | 2025-11-08 17:13:11 -0500 |
|---|---|---|
| committer | Peter Zhu <peter@peterzhu.ca> | 2025-11-08 17:58:25 -0800 |
| commit | 827f11fce3c92dce80ebc5dc80be9acdafae1173 (patch) | |
| tree | 3124a892d423c38c9b84500cef12248bf0dc4fd3 | |
| parent | 79eed1158de4164f72def32093aa31bcac339639 (diff) | |
Move rb_gc_verify_shareable to gc.c
rb_gc_verify_shareable is not GC implementation specific so it should live
in gc.c.
| -rw-r--r-- | gc.c | 78 | ||||
| -rw-r--r-- | gc/default/default.c | 61 | ||||
| -rw-r--r-- | gc/gc.h | 1 | ||||
| -rw-r--r-- | gc/gc_impl.h | 1 | ||||
| -rw-r--r-- | gc/mmtk/mmtk.c | 6 |
5 files changed, 67 insertions, 80 deletions
@@ -621,7 +621,6 @@ typedef struct gc_function_map { void (*config_set)(void *objspace_ptr, VALUE hash); void (*stress_set)(void *objspace_ptr, VALUE flag); VALUE (*stress_get)(void *objspace_ptr); - bool (*checking_shareable)(void *objspace_ptr); // Object allocation VALUE (*new_obj)(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, bool wb_protected, size_t alloc_size); size_t (*obj_slot_size)(VALUE obj); @@ -796,7 +795,6 @@ ruby_modular_gc_init(void) load_modular_gc_func(config_get); load_modular_gc_func(stress_set); load_modular_gc_func(stress_get); - load_modular_gc_func(checking_shareable); // Object allocation load_modular_gc_func(new_obj); load_modular_gc_func(obj_slot_size); @@ -877,7 +875,6 @@ ruby_modular_gc_init(void) # define rb_gc_impl_config_set rb_gc_functions.config_set # define rb_gc_impl_stress_set rb_gc_functions.stress_set # define rb_gc_impl_stress_get rb_gc_functions.stress_get -# define rb_gc_impl_checking_shareable rb_gc_functions.checking_shareable // Object allocation # define rb_gc_impl_new_obj rb_gc_functions.new_obj # define rb_gc_impl_obj_slot_size rb_gc_functions.obj_slot_size @@ -2808,19 +2805,12 @@ mark_m_tbl(void *objspace, struct rb_id_table *tbl) } } -bool -rb_gc_checking_shareable(void) -{ - return rb_gc_impl_checking_shareable(rb_gc_get_objspace()); -} - - static enum rb_id_table_iterator_result mark_const_entry_i(VALUE value, void *objspace) { const rb_const_entry_t *ce = (const rb_const_entry_t *)value; - if (!rb_gc_impl_checking_shareable(objspace)) { + if (!rb_gc_checking_shareable()) { gc_mark_internal(ce->value); gc_mark_internal(ce->file); // TODO: ce->file should be shareable? } @@ -3085,7 +3075,7 @@ gc_mark_classext_module(rb_classext_t *ext, bool prime, VALUE box_value, void *a } mark_m_tbl(objspace, RCLASSEXT_M_TBL(ext)); - if (!rb_gc_impl_checking_shareable(objspace)) { + if (!rb_gc_checking_shareable()) { // unshareable gc_mark_internal(RCLASSEXT_FIELDS_OBJ(ext)); } @@ -3156,7 +3146,7 @@ rb_gc_mark_children(void *objspace, VALUE obj) switch (BUILTIN_TYPE(obj)) { case T_CLASS: if (FL_TEST_RAW(obj, FL_SINGLETON) && - !rb_gc_impl_checking_shareable(objspace)) { + !rb_gc_checking_shareable()) { gc_mark_internal(RCLASS_ATTACHED_OBJECT(obj)); } // Continue to the shared T_CLASS/T_MODULE @@ -5441,6 +5431,68 @@ rb_gc_rp(VALUE obj) rp(obj); } +struct check_shareable_data { + VALUE parent; + long err_count; +}; + +static void +check_shareable_i(const VALUE child, void *ptr) +{ + struct check_shareable_data *data = (struct check_shareable_data *)ptr; + + if (!rb_gc_obj_shareable_p(child)) { + fprintf(stderr, "(a) "); + rb_gc_rp(data->parent); + fprintf(stderr, "(b) "); + rb_gc_rp(child); + fprintf(stderr, "check_shareable_i: shareable (a) -> unshareable (b)\n"); + + data->err_count++; + rb_bug("!! violate shareable constraint !!"); + } +} + +static bool gc_checking_shareable = false; + +static void +gc_verify_shareable(void *objspace, VALUE obj, void *data) +{ + // while gc_checking_shareable is true, + // other Ractors should not run the GC, until the flag is not local. + // TODO: remove VM locking if the flag is Ractor local + + unsigned int lev = RB_GC_VM_LOCK(); + { + gc_checking_shareable = true; + rb_objspace_reachable_objects_from(obj, check_shareable_i, (void *)data); + gc_checking_shareable = false; + } + RB_GC_VM_UNLOCK(lev); +} + +// TODO: only one level (non-recursive) +void +rb_gc_verify_shareable(VALUE obj) +{ + rb_objspace_t *objspace = rb_gc_get_objspace(); + struct check_shareable_data data = { + .parent = obj, + .err_count = 0, + }; + gc_verify_shareable(objspace, obj, &data); + + if (data.err_count > 0) { + rb_bug("rb_gc_verify_shareable"); + } +} + +bool +rb_gc_checking_shareable(void) +{ + return gc_checking_shareable; +} + /* * Document-module: ObjectSpace * diff --git a/gc/default/default.c b/gc/default/default.c index 6045cec598..f84303e02f 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -491,7 +491,6 @@ typedef struct rb_objspace { unsigned int during_minor_gc : 1; unsigned int during_incremental_marking : 1; unsigned int measure_gc : 1; - unsigned int check_shareable : 1; } flags; rb_event_flag_t hook_events; @@ -1460,13 +1459,6 @@ RVALUE_WHITE_P(rb_objspace_t *objspace, VALUE obj) } bool -rb_gc_impl_checking_shareable(void *objspace_ptr) -{ - rb_objspace_t *objspace = objspace_ptr; - return objspace->flags.check_shareable; -} - -bool rb_gc_impl_gc_enabled_p(void *objspace_ptr) { rb_objspace_t *objspace = objspace_ptr; @@ -4980,55 +4972,6 @@ check_children_i(const VALUE child, void *ptr) } } -static void -check_shareable_i(const VALUE child, void *ptr) -{ - struct verify_internal_consistency_struct *data = (struct verify_internal_consistency_struct *)ptr; - - if (!rb_gc_obj_shareable_p(child)) { - fprintf(stderr, "(a) "); - rb_gc_rp(data->parent); - fprintf(stderr, "(b) "); - rb_gc_rp(child); - fprintf(stderr, "check_shareable_i: shareable (a) -> unshareable (b)\n"); - - data->err_count++; - rb_bug("!! violate shareable constraint !!"); - } -} - -static void -gc_verify_shareable(rb_objspace_t *objspace, VALUE obj, void *data) -{ - // while objspace->flags.check_shareable is true, - // other Ractors should not run the GC, until the flag is not local. - // TODO: remove VM locking if the flag is Ractor local - - unsigned int lev = RB_GC_VM_LOCK(); - { - objspace->flags.check_shareable = true; - rb_objspace_reachable_objects_from(obj, check_shareable_i, (void *)data); - objspace->flags.check_shareable = false; - } - RB_GC_VM_UNLOCK(lev); -} - -// TODO: only one level (non-recursive) -void -rb_gc_verify_shareable(VALUE obj) -{ - rb_objspace_t *objspace = rb_gc_get_objspace(); - struct verify_internal_consistency_struct data = { - .parent = obj, - .err_count = 0, - }; - gc_verify_shareable(objspace, obj, &data); - - if (data.err_count > 0) { - rb_bug("rb_gc_verify_shareable"); - } -} - static int verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, struct verify_internal_consistency_struct *data) @@ -5061,7 +5004,7 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, } if (!is_marking(objspace) && rb_gc_obj_shareable_p(obj)) { - gc_verify_shareable(objspace, obj, data); + rb_gc_verify_shareable(obj); } if (is_incremental_marking(objspace)) { @@ -6716,7 +6659,6 @@ gc_enter(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_ gc_enter_count(event); if (RB_UNLIKELY(during_gc != 0)) rb_bug("during_gc != 0"); if (RGENGC_CHECK_MODE >= 3) gc_verify_internal_consistency(objspace); - GC_ASSERT(!objspace->flags.check_shareable); during_gc = TRUE; RUBY_DEBUG_LOG("%s (%s)",gc_enter_event_cstr(event), gc_current_status(objspace)); @@ -6730,7 +6672,6 @@ static inline void gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev) { GC_ASSERT(during_gc != 0); - GC_ASSERT(!objspace->flags.check_shareable); rb_gc_event_hook(0, RUBY_INTERNAL_EVENT_GC_EXIT); @@ -63,6 +63,7 @@ const char *rb_obj_info(VALUE obj); size_t rb_obj_memsize_of(VALUE obj); bool ruby_free_at_exit_p(void); void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *passing_data); +void rb_gc_verify_shareable(VALUE); MODULAR_GC_FN unsigned int rb_gc_vm_lock(const char *file, int line); MODULAR_GC_FN void rb_gc_vm_unlock(unsigned int lev, const char *file, int line); diff --git a/gc/gc_impl.h b/gc/gc_impl.h index 2c05fe6cff..3250483639 100644 --- a/gc/gc_impl.h +++ b/gc/gc_impl.h @@ -54,7 +54,6 @@ GC_IMPL_FN void rb_gc_impl_stress_set(void *objspace_ptr, VALUE flag); GC_IMPL_FN VALUE rb_gc_impl_stress_get(void *objspace_ptr); GC_IMPL_FN VALUE rb_gc_impl_config_get(void *objspace_ptr); GC_IMPL_FN void rb_gc_impl_config_set(void *objspace_ptr, VALUE hash); -GC_IMPL_FN bool rb_gc_impl_checking_shareable(void *objspace_ptr); // Object allocation GC_IMPL_FN VALUE rb_gc_impl_new_obj(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, bool wb_protected, size_t alloc_size); GC_IMPL_FN size_t rb_gc_impl_obj_slot_size(VALUE obj); diff --git a/gc/mmtk/mmtk.c b/gc/mmtk/mmtk.c index 5861f5e70f..9dd3129e01 100644 --- a/gc/mmtk/mmtk.c +++ b/gc/mmtk/mmtk.c @@ -1260,12 +1260,6 @@ rb_gc_impl_copy_attributes(void *objspace_ptr, VALUE dest, VALUE obj) rb_gc_impl_copy_finalizer(objspace_ptr, dest, obj); } -bool -rb_gc_impl_checking_shareable(void *ptr) -{ - return false; -} - // GC Identification const char * |
