|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T c
Length: 13251 (0x33c3) Types: TextFile Names: »compilation.texinfo«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89 └─⟦c06c473ab⟧ »./UNRELEASED/lispref.tar.Z« └─⟦1b57a2ffe⟧ └─⟦this⟧ »compilation.texinfo«
@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