Dan Sugalski wrote:

I'm about to do exceptions, and as such I wanted to give a quick warning to everyone who does Odd Things. (Which would be in the JIT, mainly :)

Because of the way exceptions are going to work, we need to make sure that the code emitted for each individual opcode is self-contained, relative to the system stack. That is to say, when an opcode is done it can't leave any cruft on the system stack, and it shouldn't expect there to be any information on the system stack.

This would mean, that current jit/i386 is not ok, because it pushes a parrot Interp* on the stack in Parrot_jit_begin and leaves it there ...


The exception system's going to be based on setjmp/longjmp[*], with a setjmp done just before entering the runloop, and longjmps done when an exception is thrown. The low-level exception handler will then unwind the interpreter stacks until it finds an exception handler, at which point it'll enter the runloop at the point the exception handler dictates.

.... but reentering the (jitted) runloop is just like Parrot_jit_begin + jump to current_pc, so it would be ok.


... So recursive calls to parrot functions can't recursively use the system stack or anything, as that'll get unwound by the low-level exception scheme and Bad Things Will Happen. And we wouldn't want that...

I don't see any recursive calls. But anyway, when on (re)entering the runloop everything gets setup as it ought to, an exception is a noop.

What I'm missing here?

The real problem is different IMHO and we had this already with perl 6 exceptions[1]: resuming after an exception may theoretically happen on an arbitrary opcode, which might be e.g. in midst of a jitted section, where parrot registers live in processor registers.
What JIT needs to know is the location of the resume opcode, to mark it as a jump target properly, so that processor registers can be setup correctly.
More problems arise here: The exception handler might use parrot registers, which might live (or better might have lived) in processor registers, which the longjmp already has destroyed.
So we IMHO need to mark each OP with a flag, if it might throw an exception and restore all processor registers to parrot registers before doing this OP.

[1] imcc marks the address of a set_addr OP as branch target, so that this basic block wouldn't be removed by dead code detection and the register allocator does know what to do. When a arbitrary opcode can jump out of the current block and resume elsewhere, the register allocator can't assign the same registers to these variables.

So we have 3 levels, where we might have troubles:
- JIT: processor registers
- IMCC: parrot registers
- HL: lexicals

leo



Reply via email to