Implementation of exception handling
David R. Chase, Mick Jordan, Wayne C. Gramlich, Kinman Chung, Howard Gayle, Peter Kiehtreiber · 2003
Exception-handling is a feature found in one form or another in various languages. Recent examples include Ada, Modula-2+, C++, Modula-3 and Eiffel. These languages all share the “termination model” of exception handling, where control transfers into the scope of the handler and activation records separating the exceptional event from its handler are discarded. One important goal for exception-handling is that the unexceptional case should execute as quickly as possible, and it is generally assumed that execution of the exceptional case may be made more expensive to further this goal (the Modula-3 report provides guidelines, both to implementors and programmers—it suggests that 10000 instructions may be spent in the exceptional case to save one instruction in the normal case). Another important goal is that a debugger should be able to manipulate exceptional events—given an exception, it should be able to determine where the exception will be caught (if anywhere) and if an exception will not be caught, then the debugger should be notified of this event in the context in which the exception was raised. It is desirable that exception-handling not impede optimization of programs, and there are situations in which support for asynchronous exceptions would be useful. This article discusses implementation techniques for exception handling, and how these goals are met (or not). Specific examples (at the machine-code level) will be presented in terms of Sparc assembly language and the Sparc System V Release 4 Processor-specific Applications Binary Interface (abbreviated as “the ABI”). The ABI (and machines which implement it, or the very-similar SunOS 4.x calling conventions) are widely available, and the author is extremely familiar with the details of this architecture and ABI. (The important things to know for most examples in this article are that call writes the current PC into register %o7, executes the next (delay slot) instruction, and transfers control to the target of the call. The standard callee-side linkage includes a save instruction, which renames register %o7 to be %i7.) I don’t know of any good references describing most of the techniques discussed in this paper. Most of what I learned, I either learned from or in the