[BUG: trunk] Lazy sweep and ObjectSpace.each_object

[email protected]$G$9!#(B

$B!!(BLazy sweep $BCf$K(B
ObjectSpace.each_object$B!JAjEv!K$r9T$&$H!"(BSEGV $B$9$k$N(B
$B$G!"2<5-$N$h$&$J%Q%C%A$r:[email protected]$7$^$7$?!#(B

32bit $B4D6-$N(B test-all $B$G!":G6a(B sdbm $B$G(B SEGV

$B$7$F$?$N$OB?J,$3$l$,LdBj!#(B

ObjectSpace.each_object $B$r;H$C$F$$$k$N$G!#(B

$B!!?dB,$G$9$,!"2<5-$N$h$&$J860x$G$O$J$$$+$H;W$$$^$9!#(B

(1) GC mark $B=N;;~!"%%V%8%’%/%H(B o1 $B$H!"$=$3$+$i;2>H$5$l$k(B o2
$B$,(B
mark $B$5$l$:!"(Bsweep $BBP>]$K$J$k(B
(2) lazy sweep $B$K$h$j!"(Bo2 $B$,2s<}$5$l$k(B
(3) ObjectSpace.each_object $B$K$h$j!"(Bo1 $B$X%"%/%;%9$9$k(B
(4) o1 $B$+$i(B o2 $B$r;2>H$7$h$&$H$7$F(B SEGV

$B!!2r7h:v$H$7$F!“CfED$5$s$K(B ObjectSpace.each_object
$B$KAjEv$9$k4X?t(B
rb_objspace_each_objects $B$r<B9T$9$kA0$K(B sweep
$B$r40A4$K=*N;$5$;$k!”$H$$$&(B
$BJ}K!$r65$($F$b$i$$$^$7$?!#(B

$B!!%P%0$N3NG’%3!<%I$H%Q%C%A$r$*Aw$j$7$^$9!#$b$7!"E,Ev$G$7$?$i<h$j9~$s$GD:(B
$B$1$k$H9,$$$G$9!#(B

$B3NG’%3!<%I!’(B

loop{
cls = (0…10_000).map{Class.new}
cls.each{|c| c.new}
ObjectSpace.each_object{|e| e.object_id; ‘’}
}

$B%Q%C%A!’(B

Index: gc.c

— gc.c (revision 29471)
+++ gc.c (working copy)
@@ -2040,6 +2040,17 @@
return FALSE;
}

+static void
+rest_sweep(rb_objspace_t *objspace)
+{

  • if (objspace->heap.sweep_slots) {
  • while (objspace->heap.sweep_slots) {
  •  lazy_sweep(objspace);
    
  • }
  • after_gc_sweep(objspace);
  • }
    +}

static void gc_marks(rb_objspace_t *objspace);

static int
@@ -2536,6 +2547,8 @@
rb_objspace_t *objspace = &rb_objspace;
volatile VALUE v;

  • rest_sweep(objspace);
  • i = 0;
    while (i < heaps_used) {
    while (0 < i && (uintptr_t)membase <
    (uintptr_t)objspace->heap.sorted[i-1].slot->membase)

$B$^$D$b$H(B $B$f$-$R$m$G$9(B

In message “Re: [ruby-dev:42369] [BUG: trunk] Lazy sweep and
ObjectSpace.each_object”
on Wed, 13 Oct 2010 14:13:46 +0900, SASADA Koichi [email protected]
writes:

|$B!!2r7h:v$H$7$F!“CfED$5$s$K(B ObjectSpace.each_object $B$KAjEv$9$k4X?t(B
|rb_objspace_each_objects $B$r<B9T$9$kA0$K(B sweep $B$r40A4$K=*N;$5$;$k!”$H$$$&(B
|$BJ}K!$r65$($F$b$i$$$^$7$?!#(B

$B%%V%8%’%/%H$,(Bsweep$BBP>]$+$I$&$+$O$o$+$k$O$:[email protected]$+$i!"(Bsweep
$B$5$l$k$O$:$N$b$N$O(Beach_object$B$NBP>]$K$7$J$$<j$b$"$k$s$8$c$J(B
$B$$$N!)(B $B$J$s$+4
0c$$$7$F$k!)(B

[email protected]$G$9!#(B

(2010/10/14 2:34), Yukihiro M. wrote:

|$B!!2r7h:v$H$7$F!“CfED$5$s$K(B ObjectSpace.each_object $B$KAjEv$9$k4X?t(B
|rb_objspace_each_objects $B$r<B9T$9$kA0$K(B sweep
$B$r40A4$K=*N;$5$;$k!”$H$$$&(B
|$BJ}K!$r65$($F$b$i$$$^$7$?!#(B

$B%%V%8%’%/%H$,(Bsweep$BBP>]$+$I$&$+$O$o$+$k$O$:[email protected]$+$i!"(Bsweep
$B$5$l$k$O$:$N$b$N$O(Beach_object$B$NBP>]$K$7$J$$<j$b$"$k$s$8$c$J(B
$B$$$N!)(B $B$J$s$+4
0c$$$7$F$k!)(B

$B!!<j$b$"$k$H;W$$$^$9!#(B

[email protected]!"(B “rb_objspace_each_objects()” $B$N;EMM>e!"(Bslot $B$r(B
callback $B$K$=$N(B
$B$^$^EO$9$h$&$K$7$F$$$k$?$a!"(Bfree / sweep $BBP>]$+$O!"(Bcallback
[email protected]$G3NG’$7$J(B
$B$1$l$P$J$j$^$;$s!#(Bfree $B%*%V%8%’%/%H$+$I$&$+$O!"(B

flag $B$,(B 0 $B$+$I$&$+(B

$B$G8+$k$3$H$,=PMh$^$9$,!"(Bsweep $BBP>]!J<B<A(B
free$B!K$G$"$k$+$I$&$+$O!"(B

slot $B$,(B sweep_slots $B$+$D!"(B
mark $B$5$l$F$$$J$$$+(B

$B$r3NG’$7$J$1$l$P$J$j$^$;$s!#(Bcallback $B$K(B sweep_slots
$B$+$I$&$+$rF~$l$k$N$b(B
[email protected]$7!"$=$b$=$b(B rb_objspace_each_objects()
$B$J$s$F;H$o$l$k$N$O%l%"%1!<(B
$B%[email protected]$7!"$^!<A4It$d$C$A$c$($P$$$$$+!"$H$$$&46$8$G$9!#(B

$B!!$H!":#5$$E$-$^$7$?$,!"(Brb_objspace_each_objects() $B$N(B callback
$B$G(B GC $B$,(B
$B5/$-$F$bF1$8LdBj$,$"$j$^$9$M!#(Bcallback $B$9$kA0$G(B sweep
$B$r40N;$9$k$h$&$KJQ(B
$B99$7$F$b!"7k6ILdBj$O;D$k$7!#$I$&$7$h$&$+$J!#(B

$B!!>e5-(B check $B$r9T$&(B rb_objspace_live_p(VALUE)
$B$_$?$$$J$N$rMQ0U$7$F!"$3$l(B
$B$r;H$&$h$&$K$7$F$b$i$&!"$H$+!)(B

nari$B$G$9!#(B

2010$BG/(B10$B7n(B14$BF|(B19:13 SASADA Koichi [email protected]:

   slot $B$,(B sweep_slots $B$+$D!"(B

$B>e5-(B check $B$r9T$&(B rb_objspace_live_p(VALUE)
$B$_$?$$$J$N$rMQ0U$7$F!"$3$l(B
$B$r;H$&$h$&$K$7$F$b$i$&!"$H$+!)(B


// SASADA Koichi at atdot dot net

rb_objspace_each_objects() $B$N<B9TA0$K$O(B sweep
$B$r40A4$K=*N;$5$;$k$3$H$K(B
$B$7$F!"<B9TCf$O(B rb_gc_disable()
$B$7$F!"<B9T8e$K85$KLa$9$h$&$K$I$&$+$J$H;W$C$?(B
$B$N$G$9$,!"$$$+$,$G$7$g$&$+!)(B

nari$B$G$9!#(B

2010$BG/(B10$B7n(B18$BF|(B13:15 SASADA Koichi [email protected]:

[email protected]$G$9!#(B

(2010/10/18 5:01), Narihiro N. wrote:

rb_objspace_each_objects() $B$N<B9TA0$K$O(B sweep $B$r40A4$K=*N;$5$;$k$3$H$K(B
$B$7$F!"<B9TCf$O(B rb_gc_disable()
$B$7$F!"<B9T8e$K85$KLa$9$h$&$K$I$&$+$J$H;W$C$?(B

$B$N$G$9$,!"$$$+$,$G$7$g$&$+!)(B

$B!!(BGC.enable $B$G2sHr$G$-$F$7$^$&!J(BSEGV
$B$9$k%Q%9$,=PMh$F$7$^$&!K$N$G$^$:$$(B
$B$N$G$O$J$$$G$7$g$&$+!#(B

$B$=$&$G$9$M!#(B

$B>/$79M$($F$$?$N$G$9$,!“Nc$($P!”(BLazy sweep $B6X;%U%i%0!J(Beager $B$K(B
sweep
[email protected]_$1$k$N$O$I$&$G$7$g$&$+!#(BRuby $BB&$+$i$O?($i$;$J$$%U%i%0$K$9$l(B
$B$P!"(BSEGV $B$9$k4m81$OKI$0$3$H$,=PMh$k$N$G$O$J$$$+$H!#(B

$B$J$k$[$I!#$=$N$h$&$K:n$C$F$_$^$9!#(B

[email protected]$G$9!#(B

(2010/10/18 5:01), Narihiro N. wrote:

rb_objspace_each_objects() $B$N<B9TA0$K$O(B sweep $B$r40A4$K=*N;$5$;$k$3$H$K(B
$B$7$F!"<B9TCf$O(B rb_gc_disable()
$B$7$F!"<B9T8e$K85$KLa$9$h$&$K$I$&$+$J$H;W$C$?(B
$B$N$G$9$,!"$$$+$,$G$7$g$&$+!)(B

$B!!(BGC.enable $B$G2sHr$G$-$F$7$^$&!J(BSEGV
$B$9$k%Q%9$,=PMh$F$7$^$&!K$N$G$^$:$$(B
$B$N$G$O$J$$$G$7$g$&$+!#(B

$B!!>/$79M$($F$$?$N$G$9$,!“Nc$($P!”(BLazy sweep $B6X;%U%i%0!J(Beager
$B$K(B sweep
[email protected]_$1$k$N$O$I$&$G$7$g$&$+!#(BRuby
$BB&$+$i$O?($i$;$J$$%U%i%0$K$9$l(B
$B$P!"(BSEGV $B$9$k4m81$OKI$0$3$H$,=PMh$k$N$G$O$J$$$+$H!#(B

nari$B$G$9!#(B

Lazy sweep $B6X;%U%i%0$r:n$j$^$7$?!#(B
$BH?BP$,$J$1$l$P%3%
%C%H$7$?$$$H;W$$$^$9!#(B

callback$B$NESCf$G(BGC$B$,8F$P$l$F(BSEGV$B$r5/$3$9$h$&$J%3!<%I$r:[email protected]$7!"DL$k$3$H$r3NG’$7$^$7$?!#(B
make check$B$bDL$k$3$H$r3NG’$7$F$$$^$9!#(B

$B3NG’%3!<%I(B:

loop {
GC.disable
10.times do
a = []
1000.times{ a << “” }
a.dup
end
GC.enable
ObjectSpace.each_object(Array) do |a|
a.map(&:object_id)
10000.times{’’.dup}
end
}

$B%Q%C%A(B:

diff --git a/gc.c b/gc.c
index b011f4a…a9a4560 100644
— a/gc.c
+++ b/gc.c
@@ -332,6 +332,7 @@ typedef struct rb_objspace {
} heap;
struct {
int dont_gc;

  • int dont_lazy_sweep;
    int during_gc;
    } flags;
    struct {
    @@ -2040,6 +2041,17 @@ lazy_sweep(rb_objspace_t *objspace)
    return FALSE;
    }

+static void
+rest_sweep(rb_objspace_t *objspace)
+{

  • if (objspace->heap.sweep_slots) {
  •   while (objspace->heap.sweep_slots) {
    
  •       lazy_sweep(objspace);
    
  •   }
    
  •   after_gc_sweep(objspace);
    
  • }
    +}

static void gc_marks(rb_objspace_t *objspace);

static int
@@ -2047,6 +2059,9 @@ gc_lazy_sweep(rb_objspace_t *objspace)
{
int res;

  • if (objspace->flags.dont_lazy_sweep)

  •    return garbage_collect(objspace);
    
  • INIT_GC_PROF_PARAMS;

    if (!ready_to_gc(objspace)) return TRUE;
    @@ -2536,6 +2551,9 @@ rb_objspace_each_objects(int (*callback)(void
    *vstart, void *vend,
    rb_objspace_t *objspace = &rb_objspace;
    volatile VALUE v;

  • rest_sweep(objspace);

  • objspace->flags.dont_lazy_sweep = TRUE;

  • i = 0;
    while (i < heaps_used) {
    while (0 < i && (uintptr_t)membase <
    (uintptr_t)objspace->heap.sorted[i-1].slot->membase)
    @@ -2562,6 +2580,7 @@ rb_objspace_each_objects(int (*callback)(void
    *vstart, void *vend,
    }
    }

  • objspace->flags.dont_lazy_sweep = FALSE;
    return;
    }

[email protected]$G$9!#(B

(2010/10/18 7:14), Narihiro N. wrote:

Lazy sweep $B6X;%U%i%0$r:n$j$^$7$?!#(B
$BH?BP$,$J$1$l$P%3%
%C%H$7$?$$$H;W$$$^$9!#(B

callback$B$NESCf$G(BGC$B$,8F$P$l$F(BSEGV$B$r5/$3$9$h$&$J%3!<%I$r:[email protected]$7!"DL$k$3$H$r3NG’$7$^$7$?!#(B

make check$B$bDL$k$3$H$r3NG’$7$F$$$^$9!#(B

[email protected]$H!“Nc$($PNc30$,=P$?>l9g!”(Bdont_lazy_sweep $B$,(B TRUE
$B$N$^$^$K$J$C$F(B
$B$7$^$&$h$&$J5$$,$7$^$9!#(Bensure $B$G0O$^$J$$$H!#(B

$BM>CL(B

$B!!$A$g$C$H4X78$J$$$G$9$,!"(Bgc_lazy_sweep()
$B$H$$$&4X?t$O!"2<[email protected]$H;W(B
$B$&$N$G$9$,!((B

$B!&$b$7!“CY1d$7$?(B slot $B$,$”$l$P!"(Bsweep $B$r$9$k(B
$B!!$3$l$G!"(Bfreelist $B$,(B NULL $B$G$J$1$l$P!"$3$3$G=*$o$j(B
$B!&(BGC $B$r3+;O!J(Bmark$B!K(B
$B!&CY1d(B sweep $B$r$7$F!"7k2L$rJV$9(B

sweep $B$H$$$&4X?t$G(B mark $B$^$G$7$A$c$&$N$O$$$$$G$7$g$&$+!#(B

$B!!$"$^$j!“BP0F$O$J$$$N$G$9$,!”$J$s$H$J$/!"(Bgarbage_collect() $B$r(B
$B:#$N(B
gc_lazy_sweep() $B$H$7$F!":#$N(B garbage_collect() $B$r!"(B
garbage_collect_eager()
$B$_$?$$$K$7$F$7$^$&$N$O$I$&[email protected]$m$&!"$H;W$$$^$7$?!#(B

nari$B$G$9!#(B

[email protected]$H!“Nc$($PNc30$,=P$?>l9g!”(Bdont_lazy_sweep $B$,(B TRUE
$B$N$^$^$K$J$C$F(B
$B$7$^$&$h$&$J5$$,$7$^$9!#(Bensure $B$G0O$^$J$$$H!#(B

$B$)$)!"$=$&$G$9$M!D!#$4;XE&$"$j$,$H$&$4$6$$$^$9!#(B
$B$=$N$h$&$J%Q%C%A$r:n$C$F$_$^$7$?!#K%a!<%k$N0lHV:G8e$KE=$jIU$1$F$*$-$^$9!#(B

sweep $B$H$$$&4X?t$G(B mark $B$^$G$7$A$c$&$N$O$$$$$G$7$g$&$+!#(B

$B$J$k$[$I!#(B
$B4X?tL>$K(Bgc_$B$H$$$&%W%l%U%#%/%9$,IU$$$F$$$k$N$G!"%^!<%/$7$F$b$$$$$N$+$J$H(B
$B$+!"$=$&$$$&[email protected]$$Lu$r;W$$$D$$$?$N$G$9$,$d$C$Q$j%@%a$G$9$M!#(B

$B$"$^$j!“BP0F$O$J$$$N$G$9$,!”$J$s$H$J$/!"(Bgarbage_collect() $B$r(B $B:#$N(B
gc_lazy_sweep() $B$H$7$F!":#$N(B garbage_collect() $B$r!"(B
garbage_collect_eager() $B$_$?$$$K$7$F$7$^$&$N$O$I$&[email protected]$m$&!"$H;W$$$^$7$?!#(B

garbage_collect_eager() $B$h$j$b(B garbage_collect_full()
$B$NJ}$,[email protected]$_(B
$B$,$"$k$N$+$J$H;W$$$^$7$?!#$3$A$i$NJ}$b2K$r8+$D$1$FD>$7$F$*$-$^$9!#(B

$B%Q%C%A(B:
diff --git a/gc.c b/gc.c
index b011f4a…ad49fd5 100644
— a/gc.c
+++ b/gc.c
@@ -332,6 +332,7 @@ typedef struct rb_objspace {
} heap;
struct {
int dont_gc;

  • int dont_lazy_sweep;
    int during_gc;
    } flags;
    struct {
    @@ -2040,6 +2041,17 @@ lazy_sweep(rb_objspace_t *objspace)
    return FALSE;
    }

+static void
+rest_sweep(rb_objspace_t *objspace)
+{

  • if (objspace->heap.sweep_slots) {
  •   while (objspace->heap.sweep_slots) {
    
  •       lazy_sweep(objspace);
    
  •   }
    
  •   after_gc_sweep(objspace);
    
  • }
    +}

static void gc_marks(rb_objspace_t *objspace);

static int
@@ -2047,6 +2059,9 @@ gc_lazy_sweep(rb_objspace_t *objspace)
{
int res;

  • if (objspace->flags.dont_lazy_sweep)

  •    return garbage_collect(objspace);
    
  • INIT_GC_PROF_PARAMS;

    if (!ready_to_gc(objspace)) return TRUE;
    @@ -2489,6 +2504,55 @@ Init_heap(void)
    init_heap(&rb_objspace);
    }

+static VALUE
+lazy_sweep_enable(void)
+{

  • rb_objspace_t *objspace = &rb_objspace;
  • objspace->flags.dont_lazy_sweep = FALSE;
  • return Qnil;
    +}

+static VALUE
+objspace_each_objects(VALUE arg)
+{

  • size_t i;
  • RVALUE *membase = 0;
  • RVALUE *pstart, *pend;
  • rb_objspace_t *objspace = &rb_objspace;
  • VALUE *args = (VALUE *)arg;
  • volatile VALUE v;
  • i = 0;
  • while (i < heaps_used) {
  • while (0 < i && (uintptr_t)membase <
    (uintptr_t)objspace->heap.sorted[i-1].slot->membase)
  •  i--;
    
  • while (i < heaps_used &&
    (uintptr_t)objspace->heap.sorted[i].slot->membase <=
    (uintptr_t)membase )
  •  i++;
    
  • if (heaps_used <= i)
  • break;
  • membase = objspace->heap.sorted[i].slot->membase;
  • pstart = objspace->heap.sorted[i].slot->slot;
  • pend = pstart + objspace->heap.sorted[i].slot->limit;
  • for (; pstart != pend; pstart++) {
  •  if (pstart->as.basic.flags) {
    
  • v = (VALUE)pstart; /* acquire to save this object */
  • break;
  •  }
    
  • }
  • if (pstart != pend) {
  •  if ((*(int (*)(void *, void *, size_t, void *))args[0])(pstart,
    

pend, sizeof(RVALUE), (void *)args[1])) {

  • return;
  •  }
    
  • }
  • }
  • return Qnil;
    +}

/*

  • rb_objspace_each_objects() is special C API to walk through
  • Ruby object space. This C API is too difficult to use it.
    @@ -2530,39 +2594,15 @@ rb_objspace_each_objects(int (*callback)(void
    *vstart, void *vend,
    size_t stride, void *d),
    void *data)
    {
  • size_t i;
  • RVALUE *membase = 0;
  • RVALUE *pstart, *pend;
  • VALUE args[2];
    rb_objspace_t *objspace = &rb_objspace;
  • volatile VALUE v;

  • i = 0;

  • while (i < heaps_used) {

  • while (0 < i && (uintptr_t)membase <
    (uintptr_t)objspace->heap.sorted[i-1].slot->membase)

  •  i--;
    
  • while (i < heaps_used &&
    (uintptr_t)objspace->heap.sorted[i].slot->membase <=
    (uintptr_t)membase )

  •  i++;
    
  • if (heaps_used <= i)

  • break;

  • membase = objspace->heap.sorted[i].slot->membase;

  • pstart = objspace->heap.sorted[i].slot->slot;

  • pend = pstart + objspace->heap.sorted[i].slot->limit;

  • for (; pstart != pend; pstart++) {

  •  if (pstart->as.basic.flags) {
    
  • v = (VALUE)pstart; /* acquire to save this object */

  • break;

  •  }
    
  • }

  • if (pstart != pend) {

  •  if ((*callback)(pstart, pend, sizeof(RVALUE), data)) {
    
  • return;

  •  }
    
  • }

  • }

  • rest_sweep(objspace);
  • objspace->flags.dont_lazy_sweep = TRUE;
  • return;
  • args[0] = (VALUE)callback;
  • args[1] = (VALUE)data;
  • rb_ensure(objspace_each_objects, (VALUE)args, lazy_sweep_enable,
    Qnil);
    }

struct os_each_struct {

$B%A%1%C%H(B #3940 $B$,99?7$5$l$^$7$?!#(B (by Anonymous)

$B%9%F!<%?%9(B Assigned$B$+$i(BClosed$B$KJQ99(B
$B?JD=(B % 0$B$+$i(B100$B$KJQ99(B

This issue was solved with changeset r29543.
Koichi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs