[comp.lang.lisp] FUNCALL question, fun facts

gjc@paradigm.com (01/30/90)

There used to be a saying, FUNCALL CONSIDERED HARMFULL..

In article <1990Jan28.175437.19293@hellgate.utah.edu>, sandra%defun.utah.edu@cs.utah.edu (Sandra J Loosemore) writes:
> In article <3277@accuvax.nwu.edu> krulwich@ils.nwu.edu (Bruce Krulwich) writes:
>>Rough experiments in Lucid CL (on a SPARCstation) indicate that there is
>>indeed twice the procedure-call overhead in calling a closure stored in a
>>lexically bound variable as in calling a global function (stored in a
>>symbol's function slot).
> 
> Many implementations do optimize FUNCALL heavily.  It is theoretically
> possible to compile FUNCALL to be just as efficient as an ordinary
> call to a named global function ...

Enough theory, here are some fun-facts-to-know and tell.

(1) In the MIT CADR or LMI LAMBDA lispmachine (FUNCALL F X) and (F X) compiled
    into *exactly* the same machine instructions.
(2) The case (FUNCALL F X) where F was a local variable was very slightly,
    but measurably FASTER than the case of (F X) where F was a "global"
(3) Symbolics and then later Texas Instruments improved on the instruction
    set such that (FUNCALL F X) and (F X) were indeed different, resulting
    in some extra overhead for the FUNCALL case, although it is very
    difficult to measure the difference.
(4) On a VAX it is quite easy to implement lexical closures in such a way
    (inline-code trampolines) such that the two cases produce the same
    instructions.
(5) On some RISC architectures, e.g. SPARC from SUN, there is different
    code produce for {This is C code now, not lisp:} (*F)(X); vs. F(X);
    and in-fact a little subroutine called POINTERCALL is called
    in the (*F)(X); case.


-GJC

(Also known as the John Silber of Lisp Implementors?)

pf@islington-terrace.csc.ti.com (Paul Fuqua) (02/17/90)

    Date: Monday, January 29, 1990  1:11pm (CST)
    From: gjc at paradigm.com
    Subject: Re: FUNCALL question, fun facts
    Newsgroups: comp.lang.lisp
    
    (1) In the MIT CADR or LMI LAMBDA lispmachine (FUNCALL F X) and (F X) compiled
        into *exactly* the same machine instructions.
    (2) The case (FUNCALL F X) where F was a local variable was very slightly,
        but measurably FASTER than the case of (F X) where F was a "global"
    (3) Symbolics and then later Texas Instruments improved on the instruction
        set such that (FUNCALL F X) and (F X) were indeed different, resulting
        in some extra overhead for the FUNCALL case, although it is very
        difficult to measure the difference.

Regarding the TI Explorer, I beg to differ.  I wrote the Release 3
function-calling microcode, which is substantially unchanged through the
current release, so I have some idea what I'm talking about.

There is only one batch of CALL instructions, used identically by both
(FUNCALL F X) and (F X).  A CALL will be slightly faster if the function
is a local variable, an argument, or popped from the stack, because
stack references don't involve an external memory access.  If the
function is global, the additional overhead is two memory references.
The additional overhead of a lexical closure is mostly just extracting
the environment structure and setting it up in a local variable.

Paul Fuqua                     pf@csc.ti.com
                               {smu,texsun,cs.utexas.edu,rice}!ti-csl!pf
Texas Instruments Computer Science Center
PO Box 655474 MS 238, Dallas, Texas 75265