[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

CATCH



    Date: Sat, 3 Nov 84 13:46:42 PST
    From: Charles Dolan <cpd at UCLA-LOCUS>

    I was wondering about the relative performance differences
    for these two uses of CATCH.

    	Non-local CATCH
	---------------
    	(lset *throw* nil)
    	(define (func)
    		(*throw* nil))

    	(catch throw
    		(bind ((*throw* throw))
    			(func))
    		OTHER CODE)

    	Local CATCH
    	-----------
    	(catch throw
    		(cond ((...) (throw nil)))
    		OTHER CODE)

TC has two strategies for compiling CATCH.  For your "local CATCH"
example, no code is generated on entry to the CATCH-expression, and the
call to the escape procedure THROW is open-coded as a jump.  (Sometimes
it also has to adjust the stack, e.g. if you do a local throw out of
some code which is computing an argument to a call.)  It knows it can do
this because the variable holding the escape procedure is referred to
only in procedure position in calls, and no such call occurs inside a
non-trivial closure.

For any other CATCH, TC generates code which allocates (conses) an
escape procedure in the heap.  Escape procedures are the same size as
cons cells, and consist of a type descriptor (identifying the object as
an escape procedure, and giving code to run when it's called) together
with a pointer to the appropriate continuation (in the stack).  So the
evaluation of the CATCH-expression in your first example will cons.

There is something else going on here, which is the BIND.  BIND is just
a macro which expands into something like

    (let (...)
      (dynamic-wind (lambda () ...)
		    (lambda () ...)
		    (lambda () ...)))

where DYNAMIC-WIND is a procedure about which TC knows nothing at all.
Since TC knows nothing about DYNAMIC-WIND, it doesn't know that the
three thunks could in principle be stack-allocated, and it therefore
conses them as full closures, probably taking two or three cells each
(depending on how many things are assigned by the BIND, and how many
local variables the body of the BIND refers to).

So your non-local CATCH is expensive not only because of the CATCH which
conses, but because of the BIND which conses.  You could get rid of the
BIND, of course, by passing the escape procedure downwards as an
argument to anyone who needs it, but that wouldn't help the CATCH.

				-Jonathan