summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2021-12-07 19:33:03 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2021-12-07 21:55:41 +0900
commitd6c5a30cfdf658280338dbb8c8b17fab3190b928 (patch)
treeaee60925739813c3de0aa49ad10fd86db46c6e72
parentec878dac90df0ca5f39e72261b8d4e2898486a93 (diff)
ObjectSpace::WeakMap#inspect: check if living object [Bug #18392]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5224
-rw-r--r--gc.c29
-rw-r--r--test/ruby/test_weakmap.rb9
2 files changed, 32 insertions, 6 deletions
diff --git a/gc.c b/gc.c
index 38f0fd2ce1..2687dbb5a6 100644
--- a/gc.c
+++ b/gc.c
@@ -12117,10 +12117,26 @@ struct wmap_iter_arg {
VALUE value;
};
+static VALUE
+wmap_inspect_append(rb_objspace_t *objspace, VALUE str, VALUE obj)
+{
+ if (SPECIAL_CONST_P(obj)) {
+ return rb_str_append(str, rb_inspect(obj));
+ }
+ else if (wmap_live_p(objspace, obj)) {
+ return rb_str_append(str, rb_any_to_s(obj));
+ }
+ else {
+ return rb_str_catf(str, "#<collected:%p>", (void*)obj);
+ }
+}
+
static int
wmap_inspect_i(st_data_t key, st_data_t val, st_data_t arg)
{
- VALUE str = (VALUE)arg;
+ struct wmap_iter_arg *argp = (struct wmap_iter_arg *)arg;
+ rb_objspace_t *objspace = argp->objspace;
+ VALUE str = argp->value;
VALUE k = (VALUE)key, v = (VALUE)val;
if (RSTRING_PTR(str)[0] == '#') {
@@ -12130,11 +12146,9 @@ wmap_inspect_i(st_data_t key, st_data_t val, st_data_t arg)
rb_str_cat2(str, ": ");
RSTRING_PTR(str)[0] = '#';
}
- k = SPECIAL_CONST_P(k) ? rb_inspect(k) : rb_any_to_s(k);
- rb_str_append(str, k);
+ wmap_inspect_append(objspace, str, k);
rb_str_cat2(str, " => ");
- v = SPECIAL_CONST_P(v) ? rb_inspect(v) : rb_any_to_s(v);
- rb_str_append(str, v);
+ wmap_inspect_append(objspace, str, v);
return ST_CONTINUE;
}
@@ -12145,11 +12159,14 @@ wmap_inspect(VALUE self)
VALUE str;
VALUE c = rb_class_name(CLASS_OF(self));
struct weakmap *w;
+ struct wmap_iter_arg args;
TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void *)self);
if (w->wmap2obj) {
- st_foreach(w->wmap2obj, wmap_inspect_i, str);
+ args.objspace = &rb_objspace;
+ args.value = str;
+ st_foreach(w->wmap2obj, wmap_inspect_i, (st_data_t)&args);
}
RSTRING_PTR(str)[0] = '#';
rb_str_cat2(str, ">");
diff --git a/test/ruby/test_weakmap.rb b/test/ruby/test_weakmap.rb
index 3b9eef770a..46d8b50c03 100644
--- a/test/ruby/test_weakmap.rb
+++ b/test/ruby/test_weakmap.rb
@@ -73,6 +73,15 @@ class TestWeakMap < Test::Unit::TestCase
@wm.inspect)
end
+ def test_inspect_garbage
+ 1000.times do |i|
+ @wm[i] = Object.new
+ @wm.inspect
+ end
+ assert_match(/\A\#<#{@wm.class.name}:[^:]++:(?:\s\d+\s=>\s\#<(?:Object|collected):[^:<>]*+>(?:,|>\z))+/,
+ @wm.inspect)
+ end
+
def test_each
m = __callee__[/test_(.*)/, 1]
x1 = Object.new