From: Asher Date: 2010-08-28T01:14:47+09:00 Subject: [ruby-core:31898] Re: Garbage Collection Question, Followup --Apple-Mail-9--324199420 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii On Aug 27, 2010, at 11:22 AM, Asher wrote: > I intend to look into the patch suggested by brabuhr@gmail.com = (https://sites.google.com/site/brentsrubypatches/), which (so far as = this issue is concerned) appears to amount to: >=20 >> VALUE *rb_gc_stack_end =3D (VALUE *)STACK_GROW_DIRECTION; >> #define rb_gc_wipe_stack() { \ >> VALUE *sp =3D alloca(0); \ >> VALUE *end =3D rb_gc_stack_end; \ >> rb_gc_stack_end =3D sp; \ >> __stack_zero(end, sp); \ >=20 > And some other basic support. I will follow up on that once I have = some time to experiment (particularly sense the patch is intended for = 1.8.7 not 1.9.2). Any particular thoughts on this approach? Presumably = there is some reason it has not been patched to do so?=20 So as I understand it the problem is: The basic Ruby stack looks like:=20 Ruby stack, root node FP* ruby root node locals =3D> st_ivar_tbl ruby root node stack SP* (ruby stack frame 1 after the = activation record) =09 So when a function call is made the stack grows to look like: ruby root node locals =3D> st_ivar_tbl ruby root node stack SP* (ruby stack frame 1 after the = activation record) ruby root first child node locals =3D> st_ivar_tbl ruby root first child node CP* So when the first child node finishes the CP* moves back to the SP and = st_ivar_tbl is no longer part of the stack, which is why nested local = variables get GC'd as expected. But when the local variable in the root node is set to nil, the local = var data for object ID in st_ivar_tbl is set to 4 instead of object ID. = This leaves a valid pointer object ID with no references.=20 But "where" is this object ID pointer if its reference in the = st_ivar_tbl is now replaced with Qnil? I presume the explanation for = this is that the object actually leaves on the heap in ObjectSpace = rather than in local variable space, which means that the object is = allocated and a reference is given to st_ivar_table, so when = st_ivar_table's reference is gone there is still a valid reference in = ObjectSpace (the heap).=20 So it seems that the root node's object is remaining around even though = there are no references because its frame has not been cleared. Is this = understanding correct?=20 So if the reference to the object is always in the heap, how does the = heap's pointer become invalidated when st_ivar_tbl is cleared, as in the = examples where it works "as expected"?=20 Perhaps there is something fundamental about local variable I am missing = in my description here? I am trying to work through these things, so = help is appreciated.=20 Thanks for patience, Asher= --Apple-Mail-9--324199420 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=us-ascii
I intend to look into the = patch suggested by brabuhr@gmail.com (https://sites.go= ogle.com/site/brentsrubypatches/), which (so far as this issue is = concerned) appears to amount to:

VALUE *rb_gc_stack_end =3D (VALUE = *)STACK_GROW_DIRECTION;
#define = rb_gc_wipe_stack() {   = \
  VALUE *sp =3D = alloca(0);         = \
  VALUE *end =3D = rb_gc_stack_end; =  \
  rb_gc_stack_end =3D = sp;           = \
  __stack_zero(end, = sp);   = = \

And some other basic support. I will follow up on that = once I have some time to experiment (particularly sense the patch is = intended for 1.8.7 not 1.9.2). Any particular thoughts on this approach? = Presumably there is some reason it has not been patched to do = so? 

So as I = understand it the problem is:

The basic Ruby = stack looks like: 

Ruby stack, root node = FP*
= ruby root node locals =3D> st_ivar_tbl
ruby root = node stack SP* (ruby stack frame 1 after the activation = record)
So when a = function call is made the stack grows to look = like:

ruby root node locals =3D> = st_ivar_tbl
ruby root node stack SP* (ruby stack frame 1 = after the activation record)
= ruby root first child node locals =3D> = st_ivar_tbl
ruby root first child = node CP*

So when the first child node finishes = the CP* moves back to the SP and st_ivar_tbl is no longer part of the = stack, which is why nested local variables get GC'd as = expected.

But when the local variable in the = root node is set to nil, the local var data for object ID in st_ivar_tbl = is set to 4 instead of object ID. This leaves a valid pointer object ID = with no references. 

But "where" is this = object ID pointer if its reference in the st_ivar_tbl is now replaced = with Qnil? I presume the explanation for this is that the object = actually leaves on the heap in ObjectSpace rather than in local variable = space, which means that the object is allocated and a reference is given = to st_ivar_table, so when st_ivar_table's reference is gone there is = still a valid reference in ObjectSpace (the = heap). 

So it seems that the root node's = object is remaining around even though there are no references because = its frame has not been cleared. Is this understanding = correct? 

So if the reference to the = object is always in the heap, how does the heap's pointer become = invalidated when st_ivar_tbl is cleared, as in the examples where it = works "as expected"? 

Perhaps there is = something fundamental about local variable I am missing in my = description here? I am trying to work through these things, so help is = appreciated. 

Thanks for = patience,
Asher
= --Apple-Mail-9--324199420--