On 21 August 2013 06:04, Jonathan S. Shapiro <[email protected]> wrote:
> The only part of this that is remotely tricky is the need to implement a
> "dummy" frame at the top of the catch block stack so that the SP can be
> properly restored if the calls made from the catch block return without
> producing further exceptions.

Well, there's a fair bit that's tricky, and control flow is only one
aspect - but actually I think it's one of the easier aspects.

In the compiler, you know you're compiling an except or finally block.
 So what is special about this code - what does it have to look like?

There are three possible forms of control flow out of a handler:  we
exit with the current exception, we exit with a new exception, and we
exit having handled the exception.  These cover both finally and
blocks that conditionally re-raise the original exception (hopefully,
with the original traceback if it fails).

We can see that 'we exit with a new exception' is just a raise, so
it's a case we are handling with the means we're just describing
anyway, so we are left with two cases.  When we have handled the
exception, we know the target, can set the stack pointer and jump
directly to the relevant code - no need to indirect through the raise
trampoline.  It's the finally case (or equivalently, reraise) that
will need to be smart about determining the next handler up the chain;
it's here that we expect to have a frame that knows how to find the
next handler and set up its arguments appropriately.

Now, aside from concerns around control flow, in order to run a
handler outside its original stack, you need to be very careful about
how you generate the code.  For example, accessing local variables in
the original frame require that you indirect against the original
stack pointer, which means you actually need to obtain it, either by
walking the stack, or by pushing it together with the handler target
onto a block stack.

While I think this is a reasonable way to implement exceptions, you do
need to consider if storing that sort of additional detail and
introducing indirections to otherwise local variables into your
exception handlers is a cost you are willing to pay in bitc for its
default exception mechanism.  It's one option, but it's not the
obvious one; other mechanisms such as transitive static or dynamic
inference as to whether or not a stack trace will ever need to be
printed from the current raise may impose lower runtime overhead.

Additionally, depending on how hackers manage "resources" (especially
the type with explicit dynamic extent, like 'with' blocks, linear
types, and stack-allocated RAII objects), the finally case may become
particularly descriptive of how fast we can unwind the stack and the
real 'performance' of the exception mechanism.

-- 
William Leslie

Notice:
Likely much of this email is, by the nature of copyright, covered
under copyright law.  You absolutely may reproduce any part of it in
accordance with the copyright law of the nation you are reading this
in.  Any attempt to deny you those rights would be illegal without
prior contractual agreement.
_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev

Reply via email to