On Tue, Dec 31, 2002 at 06:32:42PM -0800, Steve Fink wrote:
> On Dec-31, Jerome Vouillon wrote:
> > 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...
I'm thinking of something like this.
First, PMCs are not stored directly in C variables, but only in "PMC
references" (in the field "ref"). A stack of PMC references is
maintained, using the field "previous". The GC will consider all the
PMCs in the stack as part of the root.
typedef struct _PMC_ref {
PMC * ref;
_PMC_REF * previous
} PMC_ref;
These PMC references need to be initialized: the PMC pointer is set to
a valid value and they are pushed into the stack. (This function
could take a least of PMC references instead of just one.)
void init_pmc_ref (Parrot_Interp *interp, PMC_ref *ref) {
ref->ref = NULL;
ref->previous = interp->c_roots;
interp->c_roots = &ref;
}
A "scope" datastructure is used to save the current stack top, and
restore it later.
typedef struct {
struct Parrot_Interp *interp;
PMC_ref * saved_top;
} scope;
void enter_scope (Parrot_Interp *interp, scope * s) {
s->interp = interp;
s->saved_top = s->c_roots;
}
void exit_scope (scope * s) {
s->interp->c_roots = s->saved_top;
}
Then, the body of a C function would look something like this:
/* Create a new scope */
scope s;
enter_scope(interp, &s);
/* Initialize the PMC references */
PMC_ref a;
init_pmc_ref(interp, &a);
...
/* Exit the scope and return */
exit_scope(&s);
return;
I don't think there is any difficulty with exception handling :
scope s;
jmp_buf buf;
enter_scope(interp, &s);
if (setjmp(buf)) {
... /* Something that might throw an exception */
exit_scope(&s);
} else {
exit_scope(&s);
... /* Handle the exception */
}
-- Jerome