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.