> >The thread-package-compatible setjmp/longjmp can be easily implemented
> >using assembly code. It does not require access to any private data
> >structures. Note that Microsoft Windows "Structured Exception Handler"
> >works well under thread and signal. The assembly code of __try will
> >show you how to do it.
> 
> Yup, and we can use platform-specific exception handling mechanisms 
> as well, if there are any. Except...

The stack unwinding is very basic, that is why we have setjmp/longjmp.
Even it is CPU specific, it requires only very small piece of asm code,
much less than JIT. BTW, JIT needs similar kind of functionalities,
otherwise JIT will not be able to handle exceptions very fast. It will
be very awrkward to check for every null pointer and every function
return.

> >However, signal-compatible will be very difficult. It requries access
> >to ucontext, and most of thread package can not provide 100% correct
> >ucontext for signal. (The thread package may have the right info, but
> >the ucontext parameter may not have the info.)
> 
> You hit this. And we can't universally guarantee that it'll work, either.

Parrot has to handle signals, such as SIGSEGV. I believe we have to solve
this problem, no matter whether use sigjmp/longjmp as general exception
handling. In general, most of libc functions do not work well inside signal 
handler.

> >My basic suggestion is if we need convenient and fast C-based exception
> >handling, we can write our own setjmp/longjmp in assembly code. The
> >functionality will be exported as magic macros. Such as
> 
> If we're going to do this, and believe me I dearly want to, we're 
> going to be yanking ourselves out a bunch of levels. We'll be setting 
> the setjmp in runops.c just outside the interpreter loop, and yank 
> ourselves way the heck out. It's that multi-level cross-file jumping 
> that I really worry about.

The multi-level jump should not be a problem inside parrot code itself.
The GC disapline should have handled the problem already.

1) If the parrot code allocate any thing that can not be handle by GC,
it must setup exception handler to release it, see sample.

  void * mem = NULL;
  TRY {
    mem = malloc(sizeof(foo));
  } FINALLY {
    free(mem);
  } END;

2) If the parrot code allocate any thing that are finalizable, there is
no need to release them. When the object is not referenced, the next gc
will finalize it. We can still use TRY block to enfore cleanup in timely
fashion.

However, we can not use setjmp/longjmp (even parrot-specific version)
to unwind non-parrot frames. If an third party C application calls 
Parrot_xxx, the Parrot_xxx should catch any exception and translate
it into error code and returns it.

Implement parrot-specific version setjmp/longjmp will be trivial compare
to the complexity of JIT and GC. When we solved the JIT, GC, threading,
and signal handling, the problems with setjmp/longjmp should have been
solved by then. But if we only want a simple interpreter solution, there
is no need to take on this additional complexity.

Hong

Reply via email to