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

Reply via email to