Mercurial > emacs
changeset 5945:e449bfa3caae
Initial revision
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Mon, 14 Feb 1994 20:37:15 +0000 |
parents | 022fbe742832 |
children | 44d0bebba84d |
files | lispref/compile.texi |
diffstat | 1 files changed, 586 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lispref/compile.texi Mon Feb 14 20:37:15 1994 +0000 @@ -0,0 +1,586 @@ +@c -*-texinfo-*- +@c This is part of the GNU Emacs Lisp Reference Manual. +@c Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. +@c See the file elisp.texi for copying conditions. +@setfilename ../info/compile +@node Byte Compilation, Debugging, Loading, Top +@chapter Byte Compilation +@cindex byte-code +@cindex compilation + + GNU Emacs Lisp has a @dfn{compiler} that translates functions written +in Lisp into a special representation called @dfn{byte-code} that can be +executed more efficiently. The compiler replaces Lisp function +definitions with byte-code. When a byte-code function is called, its +definition is 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 recompilation. It is not, +however, as fast as true compiled code. + + In general, any version of Emacs can run byte-compiled code produced +by recent earlier versions of Emacs, but the reverse is not true. In +particular, if you compile a program with Emacs 18, you can run the +compiled code in Emacs 19, but not vice versa. + + @xref{Compilation Errors}, for how to investigate errors occurring in +byte compilation. + +@menu +* Compilation Functions:: Byte compilation functions. +* Eval During Compile:: Code to be evaluated when you compile. +* Byte-Code Objects:: The data type used for byte-compiled functions. +* Disassembly:: Disassembling byte-code; how to read byte-code. +@end menu + +@node Compilation Functions +@comment node-name, next, previous, up +@section The Compilation Functions +@cindex compilation functions + + You can byte-compile an individual function or macro definition with +the @code{byte-compile} function. You can compile a whole file with +@code{byte-compile-file}, or several files with +@code{byte-recompile-directory} or @code{batch-byte-compile}. + + When you run the byte compiler, you may get warnings in a buffer called +@samp{*Compile-Log*}. These report usage in your program that suggest a +problem, but are not necessarily erroneous. + +@cindex macro compilation + Be careful when byte-compiling code that uses macros. Macro calls are +expanded when they are compiled, so the macros must already be defined +for proper compilation. For more details, see @ref{Compiling Macros}. + + While byte-compiling a file, any @code{require} calls at top-level are +executed. One way to ensure that necessary macro definitions are +available during compilation is to require the file that defines them. +@xref{Features}. + + A byte-compiled function is not as efficient as a primitive function +written in C, but runs much faster than the version written in Lisp. +For a rough comparison, consider the example below: + +@example +@group +(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 +@end group + +@group +(silly-loop 100000) +@result{} ("Thu Jan 12 20:18:38 1989" + "Thu Jan 12 20:19:29 1989") ; @r{51 seconds} +@end group + +@group +(byte-compile 'silly-loop) +@result{} @r{[Compiled code not shown]} +@end group + +@group +(silly-loop 100000) +@result{} ("Thu Jan 12 20:21:04 1989" + "Thu Jan 12 20:21:17 1989") ; @r{13 seconds} +@end group +@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 actual results will vary greatly. + +@defun byte-compile symbol + 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 does not follow indirection to another symbol. +@code{byte-compile} does not compile macros. @code{byte-compile} +returns the new, compiled definition of @var{symbol}. + +@example +@group +(defun factorial (integer) + "Compute factorial of INTEGER." + (if (= 1 integer) 1 + (* integer (factorial (1- integer))))) + @result{} factorial +@end group + +@group +(byte-compile 'factorial) + @result{} +#[(integer) + "^H\301U\203^H^@@\301\207\302^H\303^HS!\"\207" + [integer 1 * factorial] + 4 "Compute factorial of INTEGER."] +@end group +@end example + +@noindent +The result is a compiled function object. The string it contains is the +actual byte-code; each character in it is an instruction. The vector +contains all the constants, variable names and function names used by +the function, except for certain primitives that are coded as special +instructions. +@end defun + +@deffn Command compile-defun +This command reads the defun containing point, compiles it, and +evaluates the result. If you use this on a defun that is actually a +function definition, the effect is to install a compiled version of that +function. +@end deffn + +@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}. + + Compilation works by reading the input file one form at a time. If it +is a definition of a function or macro, the compiled function or macro +definition is written out. Other forms are batched together, then each +batch is compiled, and written so that its compiled code will be +executed when the file is read. All comments are discarded when the +input file is read. + + This command returns @code{t}. When called interactively, it prompts +for the file name. + +@example +@group +% ls -l push* +-rw-r--r-- 1 lewis 791 Oct 5 20:31 push.el +@end group + +@group +(byte-compile-file "~/emacs/push.el") + @result{} t +@end group + +@group +% ls -l push* +-rw-r--r-- 1 lewis 791 Oct 5 20:31 push.el +-rw-rw-rw- 1 lewis 638 Oct 8 20:25 push.elc +@end group +@end example +@end deffn + +@deffn Command byte-recompile-directory directory flag +@cindex library compilation + 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 whether the file +should be compiled. + + The returned value of this command is unpredictable. +@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. An error in one file does +not prevent processing of subsequent files. (The file which gets the +error will not, of course, produce any compiled code.) + +@example +% emacs -batch -f batch-byte-compile *.el +@end example +@end defun + +@defun byte-code code-string data-vector max-stack +@cindex byte-code interpreter + This function actually interprets byte-code. A byte-compiled function +is actually defined with a body that calls @code{byte-code}. Don't call +this function yourself. Only the byte compiler knows how to generate +valid calls to this function. + + In newer Emacs versions (19 and up), byte-code is usually executed as +part of a compiled function object, and only rarely as part of a call to +@code{byte-code}. +@end defun + +@node Eval During Compile +@section Evaluation During Compilation + +These features permit you to write code to be evaluated during +compilation of a program. + +@defspec eval-and-compile body +This form marks @var{body} to be evaluated both when you compile the +containing code and when you run it (whether compiled or not). + +You can get a similar result by putting @var{body} in a separate file +and referring to that file with @code{require}. Using @code{require} is +preferable if there is a substantial amount of code to be executed in +this way. +@end defspec + +@defspec eval-when-compile body +This form marks @var{body} to be evaluated at compile time @emph{only}. +The result of evaluation by the compiler becomes a constant which +appears in the compiled program. When the program is interpreted, not +compiled at all, @var{body} is evaluated normally. + +At top-level, this is analogous to the Common Lisp idiom +@code{(eval-when (compile eval) @dots{})}. Elsewhere, the Common Lisp +@samp{#.} reader macro (but not when interpreting) is closer to what +@code{eval-when-compile} does. +@end defspec + +@node Byte-Code Objects +@section Byte-Code Objects +@cindex compiled function +@cindex byte-code function + + Byte-compiled functions have a special data type: they are +@dfn{byte-code function objects}. + + Internally, a byte-code function object is much like a vector; +however, the evaluator handles this data type specially when it appears +as a function to be called. The printed representation for a byte-code +function object is like that for a vector, with an additional @samp{#} +before the opening @samp{[}. + + In Emacs version 18, there was no byte-code function object data type; +compiled functions used the function @code{byte-code} to run the byte +code. + + A byte-code function object must have at least four elements; there is +no maximum number, but only the first six elements are actually used. +They are: + +@table @var +@item arglist +The list of argument symbols. + +@item byte-code +The string containing the byte-code instructions. + +@item constants +The vector of constants referenced by the byte code. + +@item stacksize +The maximum stack size this function needs. + +@item docstring +The documentation string (if any); otherwise, @code{nil}. For functions +preloaded before Emacs is dumped, this is usually an integer which is an +index into the @file{DOC} file; use @code{documentation} to convert this +into a string (@pxref{Accessing Documentation}). + +@item interactive +The interactive spec (if any). This can be a string or a Lisp +expression. It is @code{nil} for a function that isn't interactive. +@end table + +Here's an example of a byte-code function object, in printed +representation. It is the definition of the command +@code{backward-sexp}. + +@example +#[(&optional arg) + "^H\204^F^@@\301^P\302^H[!\207" + [arg 1 forward-sexp] + 2 + 254435 + "p"] +@end example + + The primitive way to create a byte-code object is with +@code{make-byte-code}: + +@defun make-byte-code &rest elements +This function constructs and returns a byte-code function object +with @var{elements} as its elements. +@end defun + + You should not try to come up with the elements for a byte-code function +yourself, because if they are inconsistent, Emacs may crash when you +call the function. Always leave it to the byte-compiler to create these +objects; it, we hope, always makes the elements consistent. + + You can access the elements of a byte-code object using @code{aref}; +you can also use @code{vconcat} to create a vector with the same +elements. + +@node Disassembly +@section Disassembled Byte-Code +@cindex disassembled byte-code + + People do not write byte-code; that job is left to the byte compiler. +But we provide a disassembler to satisfy a cat-like curiosity. The +disassembler converts the byte-compiled code into humanly readable +form. + + The byte-code interpreter is implemented as a 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 function. + + In addition to the stack, values used during byte-code execution can +be stored in ordinary Lisp variables. Variable values can be pushed +onto the stack, and variables can be set by popping the stack. + +@deffn Command 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 stream @code{standard-output}. The +argument @var{object} can be a function name or a lambda expression. + +As a special exception, if this function is used interactively, +it outputs to a buffer named @samp{*Disassemble*}. +@end deffn + + Here are two examples of using the @code{disassemble} function. We +have added explanatory comments to help you relate the byte-code to the +Lisp source; these do not appear in the output of @code{disassemble}. +These examples show unoptimized byte-code. Nowadays byte-code is +usually optimized, but we did not want to rewrite these examples, since +they still serve their purpose. + +@example +@group +(defun factorial (integer) + "Compute factorial of an integer." + (if (= 1 integer) 1 + (* integer (factorial (1- integer))))) + @result{} factorial +@end group + +@group +(factorial 4) + @result{} 24 +@end group + +@group +(disassemble 'factorial) + @print{} byte-code for factorial: + doc: Compute factorial of an integer. + args: (integer) +@end group + +@group +0 constant 1 ; @r{Push 1 onto stack.} + +1 varref integer ; @r{Get value of @code{integer}} + ; @r{from the environment} + ; @r{and push the value} + ; @r{onto the stack.} +@end group + +@group +2 eqlsign ; @r{Pop top two values off stack,} + ; @r{compare them,} + ; @r{and push result onto stack.} +@end group + +@group +3 goto-if-nil 10 ; @r{Pop and test top of stack;} + ; @r{if @code{nil}, go to 10,} + ; @r{else continue.} +@end group + +@group +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).} +@end group + +@group +10 constant * ; @r{Push symbol @code{*} onto stack.} + +11 varref integer ; @r{Push value of @code{integer} onto stack.} +@end group + +@group +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.} +@end group + +@group + ; @r{Stack now contains:} + ; @minus{} @r{decremented value of @code{integer}} + ; @minus{} @r{@code{factorial}} + ; @minus{} @r{value of @code{integer}} + ; @minus{} @r{@code{*}} +@end group + +@group +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.} +@end group + +@group + ; @r{Stack now contains:} + ; @minus{} @r{result of result of recursive} + ; @r{call to @code{factorial}} + ; @minus{} @r{value of @code{integer}} + ; @minus{} @r{@code{*}} +@end group + +@group +16 call 2 ; @r{Using the first two} + ; @r{(i.e., the top two)} + ; @r{elements of the stack} + ; @r{as arguments,} + ; @r{call the function @code{*},} + ; @r{pushing the result onto the stack.} +@end group + +@group +17 return ; @r{Return the top element} + ; @r{of the stack.} + @result{} nil +@end group +@end example + +The @code{silly-loop} function is somewhat more complex: + +@example +@group +(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 +@end group + +@group +(disassemble 'silly-loop) + @print{} 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} + ; @r{@code{current-time-string}} + ; @r{onto top of stack.} +@end group + +@group +1 call 0 ; @r{Call @code{current-time-string}} + ; @r{ with no argument,} + ; @r{ pushing result onto stack.} +@end group + +@group +2 varbind t1 ; @r{Pop stack and bind @code{t1}} + ; @r{to popped value.} +@end group + +@group +3 varref n ; @r{Get value of @code{n} from} + ; @r{the environment and push} + ; @r{the value onto the stack.} +@end group + +@group +4 sub1 ; @r{Subtract 1 from top of stack.} +@end group + +@group +5 dup ; @r{Duplicate the top of the stack;} + ; @r{i.e. copy the top of} + ; @r{the stack and push the} + ; @r{copy onto the stack.} +@end group + +@group +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}} + ; @r{copies the top of the stack} + ; @r{into the value of @code{n}} + ; @r{without popping it.} +@end group + +@group +7 constant 0 ; @r{Push 0 onto stack.} +@end group + +@group +8 gtr ; @r{Pop top two values off stack,} + ; @r{test if @var{n} is greater than 0} + ; @r{and push result onto stack.} +@end group + +@group +9 goto-if-nil-else-pop 17 ; @r{Goto 17 if @code{n} > 0} + ; @r{else pop top of stack} + ; @r{and continue} + ; @r{(this exits the while loop).} +@end group + +@group +12 constant nil ; @r{Push @code{nil} onto stack} + ; @r{(this is the body of the loop).} +@end group + +@group +13 discard ; @r{Discard result of the body} + ; @r{of the loop (a while loop} + ; @r{is always evaluated for} + ; @r{its side effects).} +@end group + +@group +14 goto 3 ; @r{Jump back to beginning} + ; @r{of while loop.} +@end group + +@group +17 discard ; @r{Discard result of while loop} + ; @r{by popping top of stack.} +@end group + +@group +18 varref t1 ; @r{Push value of @code{t1} onto stack.} +@end group + +@group +19 constant current-time-string ; @r{Push} + ; @r{@code{current-time-string}} + ; @r{onto top of stack.} +@end group + +@group +20 call 0 ; @r{Call @code{current-time-string} again.} +@end group + +@group +21 list2 ; @r{Pop top two elements off stack,} + ; @r{create a list of them,} + ; @r{and push list onto stack.} +@end group + +@group +22 unbind 1 ; @r{Unbind @code{t1} in local environment.} + +23 return ; @r{Return value of the top of stack.} + + @result{} nil +@end group +@end example + +