From 4044188266c6a305bcd72e81c8dc80524c596258 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Wed, 18 Jun 2025 13:17:24 -0700 Subject: [PATCH] Fix load catch table write barrier I tried fixing this in 521b2fcba4e96898bfd237c79f17f19530b7a030, but re-running wbcheck with the stricter WBCHECK_VERIFY_AFTER_WB, revealed that this write barrier was fired too early, before the object was actually written to the parent. This solves the issue by writing the table to the parent immediately (and using calloc so that we don't mark random garbage). --- compile.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compile.c b/compile.c index ca80e7f32d..2dc33c001a 100644 --- a/compile.c +++ b/compile.c @@ -13296,12 +13296,13 @@ ibf_dump_catch_table(struct ibf_dump *dump, const rb_iseq_t *iseq) } } -static struct iseq_catch_table * +static void ibf_load_catch_table(const struct ibf_load *load, ibf_offset_t catch_table_offset, unsigned int size, const rb_iseq_t *parent_iseq) { if (size) { - struct iseq_catch_table *table = ruby_xmalloc(iseq_catch_table_bytes(size)); + struct iseq_catch_table *table = ruby_xcalloc(1, iseq_catch_table_bytes(size)); table->size = size; + ISEQ_BODY(parent_iseq)->catch_table = table; ibf_offset_t reading_pos = catch_table_offset; @@ -13317,10 +13318,9 @@ ibf_load_catch_table(const struct ibf_load *load, ibf_offset_t catch_table_offse rb_iseq_t *catch_iseq = (rb_iseq_t *)ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)iseq_index); RB_OBJ_WRITE(parent_iseq, UNALIGNED_MEMBER_PTR(&table->entries[i], iseq), catch_iseq); } - return table; } else { - return NULL; + ISEQ_BODY(parent_iseq)->catch_table = NULL; } } @@ -13833,7 +13833,8 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) load_body->insns_info.body = ibf_load_insns_info_body(load, insns_info_body_offset, insns_info_size); load_body->insns_info.positions = ibf_load_insns_info_positions(load, insns_info_positions_offset, insns_info_size); load_body->local_table = ibf_load_local_table(load, local_table_offset, local_table_size); - load_body->catch_table = ibf_load_catch_table(load, catch_table_offset, catch_table_size, iseq); + ibf_load_catch_table(load, catch_table_offset, catch_table_size, iseq); + const rb_iseq_t *parent_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)parent_iseq_index); const rb_iseq_t *local_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)local_iseq_index); const rb_iseq_t *mandatory_only_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)mandatory_only_iseq_index);