diff --git a/gc.c b/gc.c index c2889a78c2..dc17f3bf31 100644 --- a/gc.c +++ b/gc.c @@ -3007,6 +3007,20 @@ rb_gc_location(VALUE value) return rb_gc_impl_location(rb_gc_get_objspace(), value); } +void +rb_gc_prepare_heap_process_object(VALUE obj) +{ + switch (BUILTIN_TYPE(obj)) { + case T_STRING: + // Precompute the string coderange. This both save time for when it will be + // eventually needed, and avoid mutating heap pages after a potential fork. + rb_enc_str_coderange(obj); + break; + default: + break; + } +} + void rb_gc_prepare_heap(void) { diff --git a/gc/default.c b/gc/default.c index d28c8aa553..dac7aaeed6 100644 --- a/gc/default.c +++ b/gc/default.c @@ -6763,12 +6763,8 @@ gc_set_candidate_object_i(void *vstart, void *vend, size_t stride, void *data) case T_NONE: case T_ZOMBIE: break; - case T_STRING: - // precompute the string coderange. This both save time for when it will be - // eventually needed, and avoid mutating heap pages after a potential fork. - rb_enc_str_coderange(v); - // fall through default: + rb_gc_prepare_heap_process_object(v); if (!RVALUE_OLD_P(objspace, v) && !RVALUE_WB_UNPROTECTED(objspace, v)) { RVALUE_AGE_SET_CANDIDATE(objspace, v); } diff --git a/gc/gc.h b/gc/gc.h index d5b07faf92..1cacf8a2a5 100644 --- a/gc/gc.h +++ b/gc/gc.h @@ -42,6 +42,7 @@ uint32_t rb_gc_get_shape(VALUE obj); void rb_gc_set_shape(VALUE obj, uint32_t shape_id); uint32_t rb_gc_rebuild_shape(VALUE obj, size_t heap_id); size_t rb_obj_memsize_of(VALUE obj); +void rb_gc_prepare_heap_process_object(VALUE obj); RUBY_SYMBOL_EXPORT_END void rb_ractor_finish_marking(void);