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
