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