home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.arch:10543 comp.lang.misc:3550
- Path: sparky!uunet!think.com!news!bradley
- From: bradley@marley.think.com (Bradley Kuszmaul)
- Newsgroups: comp.arch,comp.lang.misc
- Subject: Re: CLU break and continue (Was: Re: A challenge to the anti-goto)
- Date: 9 Nov 92 10:18:22
- Organization: Thinking Machines Corporation, Cambridge MA, USA
- Lines: 89
- Message-ID: <BRADLEY.92Nov9101822@marley.think.com>
- References: <1cvoctINNmhs@agate.berkeley.edu> <PSM.92Nov3165530@soma.sics.se>
- <1992Nov3.165005.18037@midway.uchicago.edu>
- <184123@pyramid.pyramid.com> <721054332.26680@minster.york.ac.uk>
- <1992Nov9.114323.22688@rdg.dec.com>
- NNTP-Posting-Host: marley.think.com
- In-reply-to: jch@rdg.dec.com's message of Mon, 9 Nov 1992 11:43:23 GMT
-
- In article <1992Nov9.114323.22688@rdg.dec.com> jch@rdg.dec.com (John Haxby) writes:
-
- ...
- It's not surprising that the Ada exception mechanism is similar to CLU's
- since CLU is one of Ada's ancestors.
-
- CLU has two exception mechanisms for slightly different purposes. One
- mechanism is for returning an exception from a procedure call: a procedure
- can signal an exception to be caught by its caller (the exception is not
- propagated up the procedure call stack) or by a generic handler for
- unhandled exceptions. The other mechanism is a local form that allows a
- block (eg in a loop or if-statement) to exit to an enclosing block.
- Apart from the local/procedure-call difference the two mechanisms are
- identical, although `signal' tends to be expensive and `exit' is simply
- an unconditional branch. ...
-
- The signal is not as expensive as you might think. This is because the
- exception is not propagated up the call stack. I remember descriptions of
- two implementations of signal, both of which had the property that
- - if the signal is not raised, there is zero runtime cost (e.g., to set up the
- signal handler.
- - if the signal is raised, only a few instructions need to execute to
- figure out where the signal handler is and to jump to it.
- - if the appropriate handler is not defined, it only takes a few more
- instructions to figure out where the `failure' handler is and to jump to
- it.
- Both implementations take advantage of the fact that the return address on
- the call stack uniquely identifies the handler for each signal.
-
- Basically the idea is that you use the return address to look up the signal
- handler in a hash table, if you don't find anything then you have to signal
- a `failure', which is handled the same way, but the compiler always sets up a
- `failure' handler for every call. The hash lookup is very fast, typically
- only a few instructions.
-
- This is in contrast to Ada, in which, for all the implementations I can
- think of
- - you pay something every time you set up a handler.
- - when a signal is raised, you have to do some search up the call stack
- for the right handler, doing some sort of hashtable lookup (or linear
- search or ...) at every activation frame.
- I can imagine some hardware support for Ada style exceptions: I believe
- that the Symbolics lisp machines provide some support for this (since these
- trace-up-the-call-stack-style-exceptions appear in LISP.) (For that matter
- I can imagine hardware support for CLU style exceptions too: it would
- probably be less hardware and would run faster...) (There ..., I included
- something relevant to comp.arch.)
-
- My opinion is that from a software engineering point of view, CLU got it
- right and Ada got it wrong. The standard argument, by example, is this:
- Suppose that you implement a "stack" abstraction, implemented using some
- sort of "array" abstraction. You might write
- ...
- pop = proc(s : stack[T]) returns(T) signals (empty)
- index : int
- index := s.index
- if(index=0) signal empty
- else s.index = index-1
- return s.array[index]
- end
- end
-
- Suppose that you make a mistake implementing your stack, and you forgot
- that your "array" abstraction provides FORTRAN arrays (that are indexed
- from 1 instead of from 0), so that the array indexing operation raises
- a `bounds' signal (i.e., the bound was invalid).
-
- The code for `pop' does not handle the `bounds' exception. What should
- be done?
- In CLU the `pop' does not handle a `bounds' exception, so `pop' raises
- `failure', meaning that the code failed. That is exactly what
- happened. If you are writing code that needs to be reliable, you can
- handle failure in various ways (e.g., by using three implementations
- and voting on the answer: If one of the implementations fails, then just
- use an answer from one of the other two), so it is much better to know
- right away that your code failed than to have the signal go
- who-knows-where.
-
- In Ada, the `bounds' is then raised by `pop', but the `pop' interface
- for `pop' does not mention `bounds', so the abstraction is broken.
- Higher up the call tree somewhere, someone who was handling a `bounds'
- for some completely other reason (e.g., because in some football-field
- abstraction, the ball might leave the playing field), gets this completely
- bogus `bounds' signal and the referee abstraction gets completely
- confused....
-
- However, the Ada committee did not buy this argument, so ...
- -Bradley
-
-