Why are stack references not counted?

BlitzMax Forums/BlitzMax Programming/Why are stack references not counted?

Fabian.(Posted 2006) [#1]
Hi!

A BlitzMax object's reference counter only counts Global and Field variables pointing to the object. Local variables aren't counted; when the GC gets called there's a loop running over the stack and counting the Locals.

Why is it done this way?
I guess it's for speed optimizing? or what is it for?
Or is there any other advantage because it's done like it is?

And as my second question: would you change this behaviour if we could have this features if all references were counted:
- multithreading (could really be possible in BMX!)
- Object Ptr not confusing the GC
- a method returning the refcount


Dreamora(Posted 2006) [#2]
Why: Because the GC knows exactly where the scope of the variable ends and thus can set it in the "clean list" for the current scope.
Its only a "real object" if it is transfered out of its scope and from that moment on its references are counted.

Multithreading wouldn't change due to that behavior. The GC is not multithreading save, that easy it is currently. It does not make any sense to try to implement it currently as you can not prevent the GC from trying to access the object to clean it. The GC would need to be replaced, from what I remember, some input has been given on that point by some experienced users in this area. Perhaps those things are implemented some day, as multithreading is definitely a must have. Systems are going 2 - 4 cores by default.

Returning refcount is currently possible. Not officially but through a little hack ( Byte Ptr(object)[-4] ). I agree that an official way to retrieve this count without the possibility to modify it would be a really good thing.

Only point I do not understand is how Object Ptr confuse the GC. They don't do it actually, the GC just ignores them. You have to manage it yourself and take care it is not pointing to a "dead" object, because the GC has no knowledge of them nor does it want to know of them as they bypass his handling system.
Or do I missunderstand what you are actually trying to say.


Fabian.(Posted 2006) [#3]
As I understand the GC it just adds a bbRelease and bbRetain to each write access to a Global or Field variable of type Object (or something derivered from it).
These macros aren't added to a write acces to a Local variable. So the program flow had to go different depending on where the Object Ptr points to: if it points to a Local variable it could simply set the assigned value, but if it points to a Global or Field variable it would need to bbRetain the assigned value and to bbRelease the previously contained value. Of course this could be done by simply comparing the address of the variable pointed by the Object Ptr variable with the current stack pos, esp, and the stack-top stored in the GCStackTop variable. But this would add a big overhead to each dereferenced write access to an Object Ptr variable, which could be done easily if you would say: bbRelease and bbRetain need to be added to each write access to object variables, so each reference is counted in the object's ref-count and there's no need to scan the stack for references.

"The GC is not multithreading save, that easy it is currently"
Here are some points which would be needed for a threadsafe GC:
- a global synchronization object (an Event object on win32) which makes sure that only one thread enters one of the GC functions. So there should be a call to WaitForSingleObject at the beginning of each GC function (GCAlloc, GCFree, collectmem...) and a call to SetEvent at the ending.
- the bbretain and bbrelease code needs lock statements to prevent simultaneous execution on multi-processor systems. the bbrelease code needs to have only one access to the ref count, which does two things: decrement the count and check whether it became zero, to eventually call GCFree
- no stack search any more, instead counting all variables with bbretain and bbrelease, so the bbGCStackTop variable wouldn't be needed any more.
I think these are the most important changes to create a threadsafe GC or is there anything else?