How are exceptions actually implemented in assembly?

Bengt Richter bokr at oz.net
Fri Jan 25 07:08:06 CET 2002


On Thu, 24 Jan 2002 17:37:38 -0600, "Jason Orendorff" <jason at jorendorff.com> wrote:

>Bengt Richter wrote:
>> I suppose you could eliminate the checking altogether in the normal path
>> if you use an "int n" instruction on x86, to break out of a path 
>> of execution like a hardware interrupt when you raise an exception,
>> but it might not be so easy to do portably.
>
>The problem is: once an exception occurs, then what?
>How do you unwind the stack and find the matching "except:" clause?
>An interrupt doesn't seem to solve this problem.
>
Not by itself, of course. And on second thought, this particular use
of a synchronous interrupt is probably just as well implemented by
a normal subroutine call. For reference, let's call this routine the
raiseException routine, whether we get there by synchronous interrupt
or ordinary call. (This would be a low level library routine to support
the compiler, not exposed to direct user use. Users just "raise" exceptions).

The question is what to do inside this routine, from which you
obviously can't usefully return normally.

I am not speaking as compiler developer, but I imagine that a compiler
could generate information stored in static tables that describe try blocks
and their associated exception handlers, to support unwinding the stack and
finding an exception handler for a raised exception.

These tables would only be looked at from the raiseException routine, and would
have no time overhead in the normal execution path. In other words, instead of
exception-raising leaving state for later testing and jumping to exception handling
code, and/or marking the limit of stack unwinding in a special stack frame flag, the
raiseException routine would unwind the stack until it found a return address
into a try block address range that had a corresponding exception handler
(recorded in the static table) for the exception being raised.

Then it would munge that frame so its return went to the exception handler in the
proper state, instead of what would have been the eventual undisturbed return
using that stack frame. A complicating factor is calling destructors during the
unwinding process, but I think it can be handled.

This is only a sketch, but I would think it could be worked out along these
lines. I'd be surprised if it's not already being done in some form somewhere.

BTW, the above is for compiling to machine language. I'm not sure how it might
translate into terms of byte code. I would think something analogous could be done,
or a hybrid approach, allowing raising exceptions within machine language extensions
(handled there and perhaps not always converted interpreter exceptions) as well as
in byte code. Anyway, I hope you didn't think I thought an interrupt by itself
was going to solve the problem ;-)

Regards,
Bengt Richter




More information about the Python-list mailing list