On Dec-31, Brent Dax wrote:
> Steve Fink:
> # 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...
> # .
> # .
> # .
> 
> Pseudocode:
> .
> .
> .
>       else {
>               Parrot_jmpbuf *jb=malloc(sizeof(Parrot_jmpbuf));
>               
>               jb->real_jmpbuf=jmpbuf;
>               jb->anchor_stack_top=interpreter->anchor_stack_top;
>               ...
>               stack_push(interpreter, interpreter->jb_stack, jb);
>       }
> }

Your pseudocode illustrates exactly what I was talking about --
including a memory allocation. And it's a memory allocation that will
really only be used in the case when a DOD is triggered, which is
exactly when we're low on memory...

It is perhaps not a fatal flaw, if we can bound the number of chained
longjmp buffers. But it does still slow down the common case.

> Yeah, I know, macros are evil, but they make this code *soooo* much
> prettier...

Actually, it seems to me if in your pseudocode you just renamed
setup_exception() to try(), then you don't really need the macro:

  if (try(interp)) {
    ...code...
  } else {
    Parrot_jmpbuf...
  }

Oops. Except I think your code, with or without macros, has a bug --
setup_exception adds another stackframe, then returns, then enters
something_that_might_throw_an_exception() which tramples
setup_exception()'s frame. So if you longjmp back, the
setup_exception() frame (including eg the 'interpreter' param) is
trashed.

So I think you're right -- you'd need a macro, but the macro would be
the entire body of the setup_exception() function. I knew there was a
reason setjmp/longjmp have always scared me.

Reply via email to