summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authortenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-04-09 23:03:40 +0000
committertenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-04-09 23:03:40 +0000
commite900bba9454f8d1a75ac5aa68a15ac21e04c5340 (patch)
tree9b3a81603fcd5ca57acb85509c48779a9c4a780a /gc.c
parentb84b8adc8910a877bf9217f95b5bfb0eea268e5a (diff)
Pin weakmap references
Weak map references can't move because the st_table needs their address as a key. But, we also need to remove T_NONE from the map so they aren't reused. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67485 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/gc.c b/gc.c
index 75c0f6917e..464f300c78 100644
--- a/gc.c
+++ b/gc.c
@@ -9767,10 +9767,24 @@ wmap_mark_map(st_data_t key, st_data_t val, st_data_t arg)
}
#endif
+static int
+wmap_pin_obj(st_data_t key, st_data_t val, st_data_t arg)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)arg;
+ VALUE obj = (VALUE)val;
+ if (obj && is_live_object(objspace, obj)) {
+ gc_pin(objspace, obj);
+ } else {
+ return ST_DELETE;
+ }
+ return ST_CONTINUE;
+}
+
static void
wmap_mark(void *ptr)
{
struct weakmap *w = ptr;
+ if (w->wmap2obj) st_foreach(w->wmap2obj, wmap_pin_obj, (st_data_t)&rb_objspace);
#if WMAP_DELETE_DEAD_OBJECT_IN_MARK
if (w->obj2wmap) st_foreach(w->obj2wmap, wmap_mark_map, (st_data_t)&rb_objspace);
#endif