From e2bbf75d5816ae2c3333e855a47cbf1b96195abd Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 20 Jun 2023 07:01:55 +0900 Subject: [PATCH] kernel.c: prepare for new recursive inspect check Like previous recursive `<=>` check, scan call stack to detect recursive `inspect` calls. We no longer need incomplete `_inspect` hack to pass around a hash table to record objects currently inspecting. --- include/mruby/internal.h | 2 ++ src/kernel.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/mruby/internal.h b/include/mruby/internal.h index 78f1d15ae..1069019d4 100644 --- a/include/mruby/internal.h +++ b/include/mruby/internal.h @@ -12,6 +12,8 @@ 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/src/kernel.c b/src/kernel.c index 049114ed3..59474be8c 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -98,6 +98,30 @@ mrb_cmp_m(mrb_state *mrb, mrb_value self) return mrb_nil_value(); } +static mrb_bool +inspect_recursive_p(mrb_state *mrb, mrb_value obj, int n) +{ + for (mrb_callinfo *ci=&mrb->c->ci[-1-n]; ci>=mrb->c->cibase; ci--) { + if (ci->mid == MRB_SYM(inspect) && + mrb_obj_eq(mrb, obj, ci->stack[0])) { + return TRUE; + } + } + return FALSE; +} + +mrb_bool +mrb_inspect_recursive_p(mrb_state *mrb, mrb_value obj) +{ + return inspect_recursive_p(mrb, obj, 0); +} + +static mrb_value +mrb_obj_inspect_recursive_p(mrb_state *mrb, mrb_value obj) +{ + return mrb_bool_value(inspect_recursive_p(mrb, obj, 1)); +} + /* 15.3.1.3.3 */ /* 15.3.1.3.33 */ /* @@ -571,6 +595,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "__to_int", mrb_ensure_int_type, MRB_ARGS_NONE()); /* internal */ mrb_define_method(mrb, krn, "__ENCODING__", mrb_encoding, MRB_ARGS_NONE()); mrb_define_method(mrb, krn, "respond_to_missing?", mrb_false, MRB_ARGS_ARG(1,1)); + mrb_define_method(mrb, krn, "__inspect_recursive?", mrb_obj_inspect_recursive_p, MRB_ARGS_NONE()); mrb_include_module(mrb, mrb->object_class, mrb->kernel_module); }