summaryrefslogtreecommitdiff
path: root/class.c
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2025-06-09 11:26:49 -0700
committerJohn Hawthorn <john@hawthorn.email>2025-07-23 14:33:55 -0700
commitd67eb07f7549508da09e6f3aa2dbe55ad0ba2da1 (patch)
treebdad5253f90cfcbbedb6fec79eabe9227e820f10 /class.c
parent54a578e72a9a13b88683fd4d12921da86c3e9cf2 (diff)
Fix missing write barrier through M_TBL
When creating a new origin in ensure_origin, we need to fire a write barrier after RCLASS_WRITE_ORIGIN. rb_class_set_super allocates, so GC could happen there, either incrementally marking or promoting the newly allocated class, and only after RCLASS_WRITE_ORIGIN will origin mark object in the M_TBL.
Diffstat (limited to 'class.c')
-rw-r--r--class.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/class.c b/class.c
index bef54eae2f..5184a96ad9 100644
--- a/class.c
+++ b/class.c
@@ -1931,6 +1931,11 @@ ensure_origin(VALUE klass)
rb_class_set_super(origin, RCLASS_SUPER(klass));
rb_class_set_super(klass, origin); // writes origin into RCLASS_SUPER(klass)
RCLASS_WRITE_ORIGIN(klass, origin);
+
+ // RCLASS_WRITE_ORIGIN marks origin as an origin, so this is the first
+ // point that it sees M_TBL and may mark it
+ rb_gc_writebarrier_remember(origin);
+
class_clear_method_table(klass);
rb_id_table_foreach(RCLASS_M_TBL(origin), cache_clear_refined_method, (void *)klass);
rb_id_table_foreach(RCLASS_M_TBL(origin), move_refined_method, (void *)klass);