class.c: add MRB_MT_FROZEN_BIT for method table layers

When mrb_mt_init_rom() is called on a class that already has a
mutable method table (from prior mrb_define_method_id() calls),
the mutable top layer is now frozen in place instead of being
left as a writable layer that wastes RAM on embedded systems.

The frozen bit (bit 29 of alloc field) marks heap-allocated
method table layers as temporarily immutable. Unlike the
readonly bit (bit 30, for true ROM), frozen layers are
automatically unfrozen when methods are later added via
mrb_define_method_raw() or removed via mrb_remove_method().
This preserves the c->mt pointer, which is critical because
iclasses (from module inclusion) hold a copy of it.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-02-19 23:25:16 +09:00
parent a208440c4f
commit cfd9214b3d
2 changed files with 19 additions and 4 deletions
+2 -1
View File
@@ -36,12 +36,13 @@ union mrb_mt_ptr {
typedef struct mrb_mt_tbl {
int size;
int alloc; /* bit 30: MRB_MT_READONLY_BIT */
int alloc; /* bit 30: MRB_MT_READONLY_BIT, bit 29: MRB_MT_FROZEN_BIT */
union mrb_mt_ptr *ptr;
struct mrb_mt_tbl *next;
} mrb_mt_tbl;
#define MRB_MT_READONLY_BIT (1 << 30)
#define MRB_MT_FROZEN_BIT (1 << 29)
#define MRB_MT_KEY_SHIFT 4
#define MRB_MT_KEY(sym, flags) ((sym)<<MRB_MT_KEY_SHIFT|(flags))
#define MRB_MT_FUNC 8 /* MRB_METHOD_FUNC_FL */