37.3. The structure of compiled functions

A compiled function consists of two objects: The function itself, containing the references to all CLISP objects needed for the bytecode, and a byte vector containing only immediate data, including the bytecode proper.

Typically, the byte vector is about twice as large as the function vector. The separation thus helps the garbage collector (since the byte vector does not need to be scanned for pointers).

A function looks like this (cf. the C type Cclosure):

name
This is the name of the function, normally a symbol or a list of the form (SETF symbol). It is used for printing the function and for error messages. This field is immutable.
codevec
This is the byte-code vector, a (VECTOR (UNSIGNED-BYTE 8)). This field is immutable.
consts[]
The remaining fields in the function object are references to other CLISP objects. These references are immutable, which is why they are called constants. (The referenced CLISP objects can be mutable objects, such as CONSes or VECTORs, however.)

The Exception to the Immutability Rule

When a generic function's dispatch code is installed, the codevec and consts fields are destructively modified.

Some of the consts can play special roles. A function looks like this, in more detail:

name
see name.
codevec
see codevec.
venv-const*
At most one object, representing the closed-up variables, representing the variables of the lexical environment in which this function was defined. It is a SIMPLE-VECTOR, which looks like this: #(next value1 ... valuen) where value1, ..., valuen are the values of the closed-up variables, and next is either NIL or a SIMPLE-VECTOR having the same structure.
block-const*
Objects representing closed-up BLOCK tags, representing the BLOCK tags of the lexical environment in which this function was defined. Each is a CONS containing in the CDR part: either a frame pointer to the block frame, or #<DISABLED>. The CAR is the block's name, for error messages only.
tagbody-const*
Objects representing closed-up TAGBODY tags, representing the TAGBODY tags of the lexical environment in which this function was defined. Each is a CONS containing in the CDR part: either a frame pointer to the TAGBODY frame, or #<DISABLED> if the TAGBODY has already been left. The CAR is a SIMPLE-VECTOR containing the names of the TAGBODY tags, for error messages only.
keyword-const*
If the function was defined with a lambda list containing &KEY, here come the symbols ("keywords"), in their correct order. They are used by the interpreter during function call.
other-const*
Other objects needed by the function's bytecode.

If venv-const, block-const, tagbody-const are all absent, the function is called autonomous. This is the case if the function does not refer to lexical variables, blocks or tags defined in compile code outside of the function. In particular, it is the case if the function is defined in a null lexical environment.

If some venv-const, block-const, or tagbody-const are present, the function (a closure) is created at runtime. The compiler only generates a prototype, containing NIL values instead of each venv-const, block-const, tagbody-const. At runtime, a function is created by copying this prototype and replacing the NIL values by the definitive ones.

The list (keyword-const* other-const*) normally does not contain duplicates, because the compiler removes duplicates when possible. (Duplicates can occur nevertheless, through the use of LOAD-TIME-VALUE.)

The codevec looks like this (cf. the C type Codevec):

spdepth_1 (2 bytes)
The 1st part of the maximal SP depth.
spdepth_jmpbufsize (2 bytes)
The jmpbufsize part of the maximal SP depth. The maximal SP depth (precomputed by the compiler) is given by spdepth_1 + spdepth_jmpbufsize * jmpbufsize.
numreq (2 bytes)
Number of required parameters.
numopt (2 bytes)
Number of optional parameters.
flags (1 byte)
bit 0
set if the function has the &REST parameter
bit 7
set if the function has &KEY parameters
bit 6
set if the function has &ALLOW-OTHER-KEYS
bit 4
set if the function is a generic function
bit 3
set if the function is a generic function and its effective method shall be returned (instead of being executed)
bit 2
set if the full original lambda list is kept in the closure object, see Section 3.3.7, “Declaration SPACE
bit 1
set if the FUNCTION DOCUMENTATION STRING is kept in the closure object, see Section 3.3.7, “Declaration SPACE
signature (1 byte)
An abbreviation code depending on numreq, numopt, flags. It is used for speeding up the function call.
numkey (2 bytes, only if the function has &KEY)
The number of &KEY parameters.
keyconsts (2 bytes, only if the function has &KEY)
The offset of the keyword-const in the function.
byte* (any number of bytes)
The bytecode instructions.

These notes document CLISP version 2.49.93+Last modified: 2018-02-19