On Dec-31, Jerome Vouillon wrote: > On Mon, Dec 30, 2002 at 04:00:55PM -0800, Steve Fink wrote: > > =head1 Solution 3: Explicity root set augmentation > > > > A final possible solution is to provide a mechanism to temporarily > > anchor an otherwise unanchored object to the root set. (eg, have an > > array of objects associated with the interpreter that are all > > considered to be part of the root set.) This has pretty much the same > > advantages and disadvantages of explicit neonate flag setting: > > > > + Simple > > + Fast DOD > > - Slow for unanchored temporaries > > - Sometimes slow for anchored objects (depending on whether they need > > to be temporarily anchored before the final anchoring) > > What do you mean by slow here?
For both of those, "slow" refers to the need to append/push infant objects onto the root set. This will slow down the common case of no DOD, because they'll need to be added to the root set and removed, without their membership ever being looked at. Objects which end up anchored may or may not have to pay that cost, because you may be able to anchor them before there is any possibility of a DOD run. As to whether that is truly slow or not -- well, I personally probably wouldn't worry about it, but I think this very concern has caused this proposal to be rejected in the past. It's certainly a good candidate for better benchmarking. If all objects have space for a pointer in them (eg the next_for_GC link), then it seems quick enough to push them onto the beginning of a list during allocation. Removing them from the list is harder, since you'd need to traverse the whole stack. Although you might be able to eliminate that problem by using both temporary anchoring and flags, so that you could mark them as "no longer temporarily anchored" with a single bit flip and strip them all out in one pass during DOD... Oops, I think I'm overdoing it again. Your later comment seems correct -- they'll always be manipulated LIFO anyway, so you can just keep a top-of-stack pointer before doing anything with them. > > - Easy to forget to remove temporaries from the root set > > - Easy to double-anchor objects and forget to remove the temporary > > anchoring > > - longjmp() can bypass the unanchoring > > The temporary objects could be stored in a stack, which is popped when > leaving the current function (both with normal exits and longjmp). > This should make it a lot less likely to forget the unanchoring. How do you do this with longjmp? I could see chaining another handler onto the longjmp context so that longjmp would backtrack through all of these allocations, but that would require allocating space for another context. And allocating space further slows down the common case... longjmp is really the major blocker for this option, so if you can work around it, then maybe we'll have something. Your stack-based approach sounds plausible as a way to make it easier to handle the bookkeeping, as long as you don't do it with macros. :-) Maybe wrapper functions? static inline retval some_op()... retval wrap_some_op(interp, args...) { Pobj *stacktop = interp->infants; retval rv = some_op(interp, args); interp->infants = stacktop; return rv; }