diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-06-05 13:52:02 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-06-05 13:52:02 +0000 |
commit | 18d4c1f044a4422fde5dde381e0812296bf2b619 (patch) | |
tree | 3bcdc87f3c1a95d16715d2f4a4645726cbc6b102 /gc.c | |
parent | eef10d71ddff0c5e6f7f5fe8f55d57a77075ebc9 (diff) | |
download | ruby-18d4c1f044a4422fde5dde381e0812296bf2b619.tar.gz |
* gc.c (os_obj_of): heaps may be modified in yield.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16845 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 21 |
1 files changed, 16 insertions, 5 deletions
@@ -1856,9 +1856,19 @@ os_obj_of(rb_objspace_t *objspace, VALUE of) { size_t i; size_t n = 0; - - for (i = 0; i < heaps_used; i++) { - RVALUE *p, *pend; + RVALUE *membase = 0; + RVALUE *p, *pend; + volatile VALUE v; + + i = 0; + while (i < heaps_used) { + while (0 < i && (uintptr_t)membase < (uintptr_t)heaps[i-1].membase) + i--; + while (i < heaps_used && (uintptr_t)heaps[i].membase <= (uintptr_t)membase ) + i++; + if (heaps_used <= i) + break; + membase = heaps[i].membase; p = heaps[i].slot; pend = p + heaps[i].limit; for (;p < pend; p++) { @@ -1872,8 +1882,9 @@ os_obj_of(rb_objspace_t *objspace, VALUE of) if (FL_TEST(p, FL_SINGLETON)) continue; default: if (!p->as.basic.klass) continue; - if (!of || rb_obj_is_kind_of((VALUE)p, of)) { - rb_yield((VALUE)p); + v = (VALUE)p; + if (!of || rb_obj_is_kind_of(v, of)) { + rb_yield(v); n++; } } |