Re: Implementation of C++ exceptions ?

chase@Think.COM (David Chase)
Mon, 11 Apr 1994 20:31:24 GMT

          From comp.compilers

Related articles
[2 earlier articles]
Re: Implementation of C++ exceptions ? mw@ipx2.rz.uni-mannheim.de (1994-04-05)
Re: Implementation of C++ exceptions ? chase@Think.COM (1994-04-05)
Re: Implementation of C++ exceptions ? schmidt@tango.ICS.UCI.EDU (Douglas C. Schmidt) (1994-04-06)
Re: Implementation of C++ exceptions ? mmc@wagner.imada.ou.dk (1994-04-07)
Implementation of C++ exceptions ? ssimmons@convex.com (1994-04-08)
Re: Implementation of C++ exceptions ? davis@ilog.ilog.fr (1994-04-11)
Re: Implementation of C++ exceptions ? chase@Think.COM (1994-04-11)
Re: Implementation of C++ exceptions ? sean@PICARD.TAMU.EDU (1994-04-12)
| List of all articles for this month |

Newsgroups: comp.compilers
From: chase@Think.COM (David Chase)
Keywords: C++, performance, design
Organization: Thinking Machines Corporation, Cambridge MA, USA
References: 94-04-019 94-04-066
Date: Mon, 11 Apr 1994 20:31:24 GMT

davis@ilog.ilog.fr (Harley Davis) writes:


|> I thought the cost of exception handling in C++ was the need to stack
|> up the code which calls the destructors of automatic variables in all
|> active blocks when unwinding to the handler. I couldn't figure out if
|> David Chase's description eliminated this cost.


[Disclaimer -- what follows is *like* what the SunPro C++ 4.0 compiler
does, but not necessarily what it does.]


My fault -- I described the data structure, but not the algorithm. Given
the tables full of (sorted) self-relative PC-ranges that are assembled by
the linker, and given that the per-binary/library .init section registers
the endpoints of each table, there is no need to stack and unstack
exception handlers in the normal case. When an an exception is thrown,
the run-time dispatcher searches the tables while unwinding the stack.
The protocol looks something like:


    recall that an exception range entry is 5 words:


    self_rel_rbegin, rlength, rbegin_rel_handler, self_rel_info, reserved


    __rt_ex_disp:
          save ...
          candidate = find_entry(%i7,%i0) ! pass it our return PC, and exception
          if (candidate != 0) {
              ! return into frame.
              range_begin = candidate + candidate[0];
              handler = range_begin + candidate[2];
              jmp handler
              restore
          } else {
              ! discard frame and try again
              restore %i0, 0, %i0
              ba __rt_ex_disp
              restore
          }


There's some details and monkey business having to do with C++ semantics
(having to do with where the exception object is supposed to be stored,
etc.) Find_entry has to interpret the info field to see if the exception
matches.


The handler for this exception runs in the same context as the other
source code surrounding it. If the exception is rethrown, or if the
handler is really just a bunch of destructors, then at the end of the
code, it does something like:


    __rt_ex_disp(exception)


Note (this is important) that this call into the runtime does NOT occur
within the same PC range that invoked this handler. This may invoke
another handler in the same frame, or it may cause the frame to be
discarded.


This all gets much more entertaining when you are trying to debug code,
because then it is not permitted to destroy the stack as you search for a
handler. Note that this also relies heavily on calling *conventions*
(probably not standards -- this are some angels-on-a-pin regarding
behavior of the ABI and compiled code in the presence of setjmp and
longjmp) that are widely followed by compilers for Sparc -- namely, that
an activation record is equivalent to a register window. (Not true for
leaf routines, but then a leaf routine by definition cannot contain a call
to __rt_ex_disp).


In the case of the debugger, what you must do is dump the register windows
to the stack (usual case for debugger) and walk the stack, passing the
return PC's so encountered to "find_entry", hoping to get a hit. The info
data structure (or else debugger information) has to include information
distinguishing true C++ handlers from destructors.


If I get really motivated, I'll try to describe how asynchronous exception
handling (could) work.


David Chase, speaking for myself
Thinking Machines Corp.
--


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.