>  STRING * concat (STRING* a, STRING* b, STRING* c) {
>    PARROT_start();
>    PARROT_str_params_3(a, b, c);
>    PARROT_str_local_2(d, e);
>
>    d = string_concat(a, b);
>    e = string_concat(d, c);
>
>    PARROT_return(e);
>  }

Yet more ideas. Woohoo! :)

I considered this kind of approach myself, but
discarded it due to the ton of extraneous code you have to write to do the
simplest of things. :( I'm not sure if the other people have considered
it, discarded it, or are still considering it.

As far as the pros/cons...

First, it requires you write in a pseudo-language to define your local PMC
headers and how to return data. I'm sure the macro freaks that have been
scarred by perl5 will jump on here and beat you down in a few hours or so.
:)

Can you provide an implementation of the macros you described above? I
have a few concerns which I'm not sure if they are addressed. For example:

PARROT_str_local(d)
I'm assuming it puts a reference to d onto the rooted stack. It would also
need to initialize d to NULL to avoid pointing at garbage buffers.

PARROT_str_params_3(a, b, c);
What's the point of this? With rule 5 that prevents function call nesting,
you're guaranteed of all your arguments being rooted. I think you can lose
either the nesting requirement or the str_params requirement.

PARROT_return(e);
I'm assuming this backs the stack up to the place pointed to by
PARROT_start(), right? This means during a longjmp, the stack won't be
backed up properly until another PARROT_return() is called, somewhere
farther up the chain, right?

Finally, I think Dan has already outlawed longjmp due to problems with
threading, but he'll have to elaborate on that. I agree my most recently
stated approach is not longjmp safe since it could leave neonate set on
certain buffers/pmcs.


Finally, in response to my original post, you asked:

> Suppose your C code builds a nested datastructure.  For instance,
> it creates some strings and add them to a hash-table.  The hash-table is
> then returned.  Should it clear the neonate flag of the strings?

I think I'd have to say...don't do that. Ops and functions shouldn't be
building large data structures, imo. Stuff like buliding large hashes
and/or arrays of data should be done in opcode, in perl code, or whatever
language is operating on parrot.

If you *really* need to operate on a nested datastructure, and you're
going to hold it against my proposal, then there are two options.

a) write code like:
base = newbasepmc #nenoate pmc
other = newchildpmc #also neonate
base->add(other) #even if collecting/dod'ing, can't collect above two
done_with_pmc(other) #un-neonates it, since it's attached to a root (neonate0 set
....repeat...

It works, and then you just need to worry about what to do with your
'base' at the end of the function (to un-neonate it or not).

b) make a done_with_children_of_pmc() style function. it hijacks
onto the tracing functionality inherent in the DOD code, and searches for
a contiguous selection of neonate buffers and pointers eminating from
the pmc we pass in, and un-neonates them, leaving the passed-in-pmc
neonated. Since everything we do in the function is nenoate, everything we
construct into this base pmc should be contiguously neonate, if that
makes sense.

Granted, it's a little bit expensive to do the tracing, but you shouldn't
need to trace too deep at all, and its time is proportional to the size of
the nested data structure you are creating.

Does that help?
Mike Lambert

PS: Oh, and I forgot to mention in my previous proposal about the need for
nenonating pmc headers, and to look into what functions need to un-neonate
pmc headers. That should be localized to the vtable methods, which are
sort of a mess right now anyway with the transmogrification of vtables and
have other GC problems.


Reply via email to