From 2735340702ac767a7fe91ac353f7c4b2ff005e27 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 7 Jul 2025 14:52:02 +0900 Subject: [PATCH] kernel.c: remove mrb_inspect_recursive_p(); #5531 And use mrb_recursive_method_p() and its helper methods. Co-authored-by: Claude --- include/mruby/internal.h | 2 -- mrbgems/mruby-set/src/set.c | 2 +- mrbgems/mruby-struct/src/struct.c | 2 +- src/array.c | 2 +- src/hash.c | 59 +------------------------------ src/kernel.c | 6 ---- src/variable.c | 2 +- 7 files changed, 5 insertions(+), 70 deletions(-) diff --git a/include/mruby/internal.h b/include/mruby/internal.h index e4be2d1ac..a05a1a521 100644 --- a/include/mruby/internal.h +++ b/include/mruby/internal.h @@ -12,8 +12,6 @@ void mrb_ary_decref(mrb_state*, mrb_shared_array*); mrb_value mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len); #endif -mrb_bool mrb_inspect_recursive_p(mrb_state *mrb, mrb_value self); - #ifdef MRUBY_CLASS_H struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym); struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym); diff --git a/mrbgems/mruby-set/src/set.c b/mrbgems/mruby-set/src/set.c index 7e25a9c1c..20022482c 100644 --- a/mrbgems/mruby-set/src/set.c +++ b/mrbgems/mruby-set/src/set.c @@ -1380,7 +1380,7 @@ set_inspect(mrb_state *mrb, mrb_value self) } /* Handle recursive inspection */ - if (mrb_inspect_recursive_p(mrb, self)) { + if (MRB_RECURSIVE_UNARY_P(mrb, MRB_SYM(inspect), self)) { return mrb_format(mrb, "%s[...]", classname); } diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index eec7dc045..4c4a23272 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -647,7 +647,7 @@ mrb_struct_to_s(mrb_state *mrb, mrb_value self) mrb_str_cat_str(mrb, ret, cname); mrb_str_cat_lit(mrb, ret, " "); } - if (mrb_inspect_recursive_p(mrb, self)) { + if (MRB_RECURSIVE_UNARY_P(mrb, MRB_SYM(inspect), self)) { mrb_str_cat_lit(mrb, ret, "...>"); return ret; } diff --git a/src/array.c b/src/array.c index bb4aeb4cf..28af8d5c4 100644 --- a/src/array.c +++ b/src/array.c @@ -1626,7 +1626,7 @@ mrb_ary_to_s(mrb_state *mrb, mrb_value self) mrb->c->ci->mid = MRB_SYM(inspect); mrb_value ret = mrb_str_new_lit(mrb, "["); int ai = mrb_gc_arena_save(mrb); - if (mrb_inspect_recursive_p(mrb, self)) { + if (MRB_RECURSIVE_UNARY_P(mrb, MRB_SYM(inspect), self)) { mrb_str_cat_lit(mrb, ret, "...]"); return ret; } diff --git a/src/hash.c b/src/hash.c index 8f7e57dc8..b8ac9fd48 100644 --- a/src/hash.c +++ b/src/hash.c @@ -2032,7 +2032,7 @@ mrb_hash_to_s(mrb_state *mrb, mrb_value self) mrb->c->ci->mid = MRB_SYM(inspect); mrb_value ret = mrb_str_new_lit(mrb, "{"); int ai = mrb_gc_arena_save(mrb); - if (mrb_inspect_recursive_p(mrb, self)) { + if (MRB_RECURSIVE_UNARY_P(mrb, MRB_SYM(inspect), self)) { mrb_str_cat_lit(mrb, ret, "...}"); return ret; } @@ -2125,62 +2125,6 @@ mrb_hash_rassoc(mrb_state *mrb, mrb_value hash) return mrb_nil_value(); } -/* - * Hash recursion detection for equality comparison - * - * This implements a memory-efficient recursion detection mechanism for Hash#== and Hash#eql? - * to prevent SystemStackError when comparing mutually recursive hash structures. - * - * Background: - * - Issue: Hash#eql? caused infinite recursion and stack overflow with recursive hashes - * - Example: a = {}; b = {}; a[:self] = a; a[:other] = b; b[:self] = b; b[:other] = a; a.eql?(b) - * - * Solution: - * - Uses call stack inspection (similar to inspect_recursive_p) to detect recursion - * - Minimal memory overhead - examines existing call frames without additional storage - * - Returns FALSE when recursion detected (conservative approach for mruby's constraints) - * - Preserves all normal equality behavior for non-recursive cases - * - * Design considerations: - * - Memory > Performance > Readability (mruby design priority) - * - Compatible with mruby's embedded/memory-constrained environment - * - Uses established pattern from kernel.c inspect_recursive_p implementation - */ - -static mrb_bool -hash_eql_recursive_p(mrb_state *mrb, mrb_value obj) -{ - /* Look for recursive eql? calls on the same object in the call stack - * Start from ci[-2] to skip current call frame (ci[-1] is __eql_recursive_p?, ci[0] is eql?) - */ - for (mrb_callinfo *ci=&mrb->c->ci[-2]; ci>=mrb->c->cibase; ci--) { - if (ci->mid == MRB_SYM_Q(eql) && - mrb_obj_eq(mrb, obj, ci->stack[0])) { - return TRUE; - } - } - return FALSE; -} - -static mrb_bool -hash_equal_recursive_p(mrb_state *mrb, mrb_value obj) -{ - /* Look for recursive == calls on the same object in the call stack */ - for (mrb_callinfo *ci=&mrb->c->ci[-2]; ci>=mrb->c->cibase; ci--) { - if (ci->mid == MRB_OPSYM(eq) && - mrb_obj_eq(mrb, obj, ci->stack[0])) { - return TRUE; - } - } - return FALSE; -} - -static mrb_value -mrb_hash_eql_recursive_p(mrb_state *mrb, mrb_value self) -{ - return mrb_bool_value(hash_eql_recursive_p(mrb, self)); -} - /* 15.2.13.4.1 */ static mrb_value mrb_hash_equal(mrb_state *mrb, mrb_value hash) @@ -2313,5 +2257,4 @@ mrb_init_hash(mrb_state *mrb) mrb_define_method_id(mrb, h, MRB_SYM(rassoc), mrb_hash_rassoc, MRB_ARGS_REQ(1)); mrb_define_method_id(mrb, h, MRB_SYM(__merge), mrb_hash_merge_m, MRB_ARGS_REQ(1)); mrb_define_method_id(mrb, h, MRB_SYM(__compact), mrb_hash_compact, MRB_ARGS_NONE()); /* implementation of Hash#compact! */ - mrb_define_private_method_id(mrb, h, MRB_SYM_Q(__eql_recursive_p), mrb_hash_eql_recursive_p, MRB_ARGS_NONE()); /* recursion detection for Hash#eql? */ } diff --git a/src/kernel.c b/src/kernel.c index 0bcb71d33..b39d31109 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -126,12 +126,6 @@ mrb_recursive_method_p(mrb_state *mrb, mrb_sym mid, mrb_value obj1, mrb_value ob #define MRB_RECURSIVE_BINARY_P(mrb, mid, obj1, obj2) \ mrb_recursive_method_p(mrb, mid, obj1, obj2) -mrb_bool -mrb_inspect_recursive_p(mrb_state *mrb, mrb_value obj) -{ - return MRB_RECURSIVE_UNARY_P(mrb, MRB_SYM(inspect), obj); -} - static mrb_value mrb_obj_method_recursive_p(mrb_state *mrb, mrb_value obj) { diff --git a/src/variable.c b/src/variable.c index 75f5254b3..70d27c626 100644 --- a/src/variable.c +++ b/src/variable.c @@ -636,7 +636,7 @@ mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj) mrb_str_cat_lit(mrb, str, ":"); mrb_str_cat_str(mrb, str, mrb_ptr_to_str(mrb, obj)); - if (mrb_inspect_recursive_p(mrb, mrb_obj_value(obj))) { + if (MRB_RECURSIVE_UNARY_P(mrb, MRB_SYM(inspect), mrb_obj_value(obj))) { mrb_str_cat_lit(mrb, str, " ...>"); return str; }