Okay. I have yet another idea for solving our infant mortality problem,
which I think Dan might like. :)

The neonate idea originally was intended to be set on *all* headers
returned by the memory system, and they'd be reset by a clear_neonate op.
At least, that's how I understood it. A straightforward implementation of
the above is about 50% slower than it was before, so I think that rules
this option out.

The current code (without this patch), adds neonate wherever it discovers
that it is needed, and turns it off when it is done. This was quite
efficient, but required the user to constantly think about what functions
could cause GC, etc. It was rather error-prone.

If I understood Dan correctly on IRC yesterday, he was proposing that our
current approach of handling infant mortality everywhere it can occur, is
the 'correct' approach. It definitely buys us speed, but as mentioned
above, it's somewhat error prone. The below is an attempt to try and
convince Dan that in lieu of hardcore GC-everywhere programming, there is
a middle ground. I believe we need a middle ground because forcing users
to learn the quirks of our GC system makes parrot programming less fun,
and raises Parrot's barrier to entry.

As I was working on my revised GC system, I came up with a relaxation of
the above that should be easier on programmers, and yet still be fast.
It's not revolutionary by any means, but rather grabbing bits and pieces
of different people's solutions. When you call new_*_header, the neonate
flag is automatically turned on for you. As a programmer writing a
function, you explicitly turn off the neonate flag when you attach it to
the root set, or let it die on the stack. If you return it, you don't do
anything, as it becomes the caller's job to handle.

Neonate guarantees that it won't be collected, avoiding infant mortality.
The programmer does not have to explicitly turn it on. Just turn it off.

>From a cursory glance over string.c, only string_concat and string_compare
create strings which die within the scope of that function, and thus need
to be modified.

This approach would complicate many of our string .ops, however. Stuff
like "$1 = s" needs to turn off the neonate flag. Perhaps we can encode
logic into the ops2c converter to turn off the neonate flag for things
that it can detect, or perhaps we can require the user to do it because
automated converters are guaranteed to fail. Core.ops requires a lot of
such modifications, however. Things like err, open, readline, print, read,
write, clone, set, set_keyed, the various string ops (substr, pack, etc),
and savec, all require modification.

I think these guidelines make it easy for non-GC-programmers to writ
GC-dafe code, since they do not need to be aware of what allocates memory,
and what does not.

What do people think of this approach?
Mike Lambert

Reply via email to