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.