DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T c

⟦a5315926c⟧ TextFile

    Length: 13251 (0x33c3)
    Types: TextFile
    Names: »compilation.texinfo«

Derivation

└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
    └─⟦c06c473ab⟧ »./UNRELEASED/lispref.tar.Z« 
        └─⟦1b57a2ffe⟧ 
            └─⟦this⟧ »compilation.texinfo« 

TextFile

@setfilename ../info/compilation
@node Byte Compilation, Debugging, Loading, Top
@chapter Byte Compilation

@cindex compilation
  GNU Emacs Lisp has a compiler which translates functions from
lambda-expressions into a special form called @dfn{byte code} which can
be executed more efficiently.  The compiler replaces each function
definition with byte code.  When a byte code file is called, its definition
is then evaluated by the @dfn{byte code interpreter}.

  Because the byte compiled code is evaluated by the byte-code
interpreter, instead of being executed directly by the machine's
hardware (as true compiled code is), byte-code is completely
transportable from machine to machine without re-compilation.  But it
is not as fast as true compiled code.

@menu
* Compilation Functions::       Byte compilation functions.
* Disassembly::                 Disassembled byte code
@end menu

@node Compilation Functions, Disassembly, Byte Compilation, Byte Compilation
@comment  node-name,  next,  previous,  up
@section The Compilation Functions
@cindex compilation functions

  An individual function or macro definition may be byte-compiled with
the @code{byte-compile} function.  A whole file may be byte-compiled
with @code{byte-compile-file} and several files may be byte-compiled
with @code{byte-recompile-directory} or @code{batch-byte-compile}.
Only @code{defun} and @code{defmacro} forms in a file are
byte-compiled; other top-level forms are unaltered byte-compilation.

@cindex macro compilation
  Be careful when byte compiling code that
uses macros since macro calls are expanded when they are compiled and
therefore the macros must already be defined for proper compilation.
For more details, @pxref{Macros}. 

  While byte-compiling a file, any @code{require} calls at
top-level are executed.  This is one way to ensure that required macro
definitions are available during compilation: require the file that
defines them.  @xref{Features}.

  A byte compiled function is not as efficient as a primitive function
written in C, but it will run much faster than the interpreted version.
As a rough comparison, consider the example below:

@example
(defun silly-loop (n)
  "Return time before and after N iterations of a loop."
  (let ((t1 (current-time-string)))
    (while (> (setq n (1- n)) 
              0))
    (list t1 (current-time-string))
    ))
     @result{} silly-loop

(silly-loop 100000)
     @result{} ("Thu Jan 12 20:18:38 1989" 
        "Thu Jan 12 20:19:29 1989")  ; @r{51 secconds}

(byte-compile 'silly-loop)
     @result{} @r{[Compiled code not shown]}

(silly-loop 100000)
     @result{} ("Thu Jan 12 20:21:04 1989" 
    "Thu Jan 12 20:21:17 1989")  ; @r{13 seconds}
@end example

  In this example, the interpreted code required 51 seconds to run, whereas the
byte compiled code required 13 seconds.  These results are representative, but
there will be great variability depending upon the specific functions
called.

@defun byte-compile symbol
@cindex function cell
  This function byte-compiles the function definition of @var{symbol},
replacing the previous definition with the compiled one.  The function
definition of @var{symbol} must be the actual code for the function;
i.e., the compiler will not follow indirection to another symbol.
@code{byte-compile} does not compile macros.

  The @code{byte-compile} function is not autoloaded as are
@code{byte-compile-file} and @code{byte-recompile-directory}.  

@example
(defun factorial (integer)
  "Compute factorial of INTEGER."
  (if (= 1 integer) 1
    (* integer (factorial (1- integer)))))
     @result{} factorial

(byte-compile 'factorial)
     @result{} (lambda (integer) 
                 "Compute factorial of INTEGER." 
                 (byte-code "\301^HU\203
                 ^@@\301\202^Q^@@\302^H\303^HS!\"\207"
                            [integer 1 * factorial] 4))
@end example
@end defun

@deffn Command byte-compile-file filename
  This function compiles a file of Lisp code named @var{filename} into
a file of byte code.  The output file's name is made by appending
@samp{c} to the end of @var{filename}.

  Each form in the input file read.  If it returns a function or
macro, the compiled function or macro definition is written out.
Other forms are copied in unchanged.  All comments are discarded.

  When called interactively, this command prompts you for the
filename.

@example
% ls -l push*
-rw-r--r--  1 lewis    0             791 Oct  5 20:31 push.el

(byte-compile-file "~/emacs/push.el")
     @result{} t

% ls -l push*
-rw-r--r--  1 lewis    0             791 Oct  5 20:31 push.el
-rw-rw-rw-  1 lewis    0             638 Oct  8 20:25 push.elc
@end example
@end deffn

@deffn Command byte-recompile-directory directory flag
@cindex libraries
  This function recompiles every @samp{.el} file in @var{directory} that
needs recompilation.  A file needs recompilation if a @samp{.elc} file
exists but is older than the @samp{.el} file.

  If a @samp{.el} file exists, but there is no corresponding @samp{.elc}
file, then @var{flag} is examined.  If it is @code{nil}, the file is
ignored.  If it is non-@code{nil}, the user is asked if the file should be
compiled.
@end deffn

@defun batch-byte-compile
  This function runs @code{byte-compile-file} on the files remaining on the
command line.  This function must be used only in a batch execution of
Emacs, as it kills Emacs on completion.  Each file will be processed, even
if an error occurs while compiling a previous file.  (The file with the
error will not produce any compiled code, of course.)

@example
% emacs -batch -f batch-byte-compile *.el
@end example
@end defun

@defun byte-code code-string data-vector max-stack
@cindex lisp interpreter
@cindex byte-code interpreter
  This is the function that actually interprets the byte code.  A
byte-compiled function is actually defined with a body that calls
@code{byte-code}.  Don't call this function yourself!
@end defun

@node  Disassembly, , Compilation Functions, Byte Compilation
@comment  node-name,  next,  previous,  up
@section Dissassembled Byte Code
@cindex dissassembled byte code

  People never write byte code; that job is left to the byte compiler.
But a disassembler has been provided to satisfy a cat-like curiosity.
The disassembler converts the byte-compiled code into a humanly readable
form.

  The byte code interpreter is implemented as a very simple stack
machine.  Values get stored by being pushed onto the stack, and are
popped off and manipulated, the results being pushed back onto the
stack.  When a function returns, the top of the stack is popped and
returned as the value of the fucntion.

  In addition to the stack, variables bound in the environment can
also hold values during execution.  The values of such variables can
be pushed onto the stack, or the variables can be set by popping the
stack.

@defun disassemble object &optional stream
  This function prints the disassembled code for @var{object}.  If
@var{stream} is supplied, then output goes there.  Otherwise, the
disassembled code is printed to the standard output.  @var{object} can
be a function name or a lambda expression.
@end defun

  Here are two examples of using the @code{disassemble} function.  The
comments added to the examples do not appear in the output of
@code{disassemble}.

@example
(defun factorial (integer)
  "Compute factorial of an integer."
  (if (= 1 integer) 1
    (* integer (factorial (1- integer)))))
     @result{} factorial

(factorial 4)
     @result{} 24

(disassemble 'factorial)
     @result{} byte code for factorial:
 doc: Compute factorial of an integer.
 args: (integer)

0   constant 1              ; @r{push 1 onto stack}

1   varref   integer        ; @r{get value of @code{integer} from the environment}
                            ;     @r{and push the value onto the stack}

2   eqlsign                 ; @r{pop top two values off stack,}
                            ;     @r{compare them,}
                            ;     @r{and push result onto stack}

3   goto-if-nil 10          ; @r{pop and test top of stack;}
                            ;     @r{if @code{nil}, go to 10,}
                            ;     @r{else continue}

6   constant 1              ; @r{push 1 onto top of stack}

7   goto     17             ; @r{go to 17 (in this case, 1 will be}
                            ;     @r{returned by the function)}

10  constant *              ; @r{push symbol @code{*} onto stack}

11  varref   integer        ; @r{push value of @code{integer} onto stack}

12  constant factorial      ; @r{push @code{factorial} onto stack}

13  varref   integer        ; @r{push value of @code{integer} onto stack}

14  sub1                    ; @r{pop @code{integer}, decrement value,}
                            ;     @r{push new value onto stack}

                        ; @r{stack now is:}
                        ;     @r{decremented value of @code{integer}}
                        ;     @r{@code{factorial}} 
                        ;     @r{value of @code{integer}}
                        ;     @r{@code{*}}

15  call     1              ; @r{call function @code{factorial} using}
                            ;     @r{the first (i.e., the top) element}
                            ;     @r{of the stack as the argument;}
                            ;     @r{push returned value onto stack}

                        ; @r{stack now is:}
                        ;        @r{result of result of recursive}
                        ;             @r{call to @code{factorial}}
                        ;        @r{value of @code{integer}}
                        ;        @r{@code{*}}

16  call     2              ; @r{using the first two (i.e., the top two)}
                            ;     @r{elements of the stack as arguments,}
                            ;     @r{call the function @code{*},}
                            ;     @r{pushing the result onto the stack}

17  return                  ; @r{return the top element of the stack}

     @result{} nil
@end example

The @code{silly-loop} function is somewhat more complex:

@example
(defun silly-loop (n)
  "Return time before and after N iterations of a loop."
  (let ((t1 (current-time-string)))
    (while (> (setq n (1- n)) 
              0))
    (list t1 (current-time-string))
    ))
     @result{} silly-loop

(disassemble 'silly-loop)
     @result{} byte code for silly-loop:
 doc: Return time before and after N iterations of a loop.
 args: (n)

0   constant current-time-string      ; @r{push @code{current-time-string}}
                                      ;     @r{onto top of stack}

1   call     0              ; @r{call @code{current-time-string} with no}
                            ;     @r{argument, pushing result onto stack}

2   varbind  t1             ; @r{pop stack and bind @code{t1} to popped value}

3   varref   n              ; @r{get value of @code{n} from the environment}
                            ;     @r{and push the value onto the stack}

4   sub1                    ; @r{subtract 1 from top of stack}

5   dup                     ; @r{duplicate the top of the stack;}
                            ;     @r{i.e. copy the top of the stack}
                            ;     @r{and push the copy onto the stack}

6   varset   n              ; @r{pop the top of the stack,}
                            ;     @r{and bind @code{n} to the value}

                    ; @r{in effect, the sequence @code{dup varset} copies}
                    ; @r{the top of the stack into the value of @code{n}}
                    ; @r{without popping it}

7   constant 0              ; @r{push 0 onto stack}

8   gtr                     ; @r{pop top two values off stack,}
                            ;     @r{test if @var{n} is greater than 0}
                            ;     @r{and push result onto stack}

9   goto-if-nil-else-pop 17     ; @r{goto 17 if @code{n} > 0 else}
                                ;     @r{pop top of stack and continue}
                                ;     @r{(this exits the while loop)}

12  constant nil            ; @r{push @code{nil} onto stack}
                            ;     @r{(this is the body of the loop)}

13  discard                 ; @r{discard result of the body of the loop}
                            ;     @r{(a while loop is always evaluated}
                            ;     @r{for its side effects)}

14  goto     3              ; @r{jump back to beginning of while loop}

17  discard                 ; @r{discard result of while loop}
                            ;     @r{by popping top of stack}

18  varref   t1             ; @r{push value of @code{t1} onto stack}

19  constant current-time-string      ; @r{push @code{current-time-string}}
                                      ;     @r{onto top of stack}

20  call     0              ; @r{call @code{current-time-string} again}

21  list2                   ; @r{pop top two elements off stack,}
                            ;     @r{create a list of them,}
                            ;     @r{and push list onto stack}

22  unbind   1              ; @r{unbind t1 in local environment}

23  return                  ; @r{return value of the top of stack}

     @result{} nil
@end example