Next: Modular arithmetic, Up: Efficiency
SBCL has limited support for performing allocation on the stack when a
variable is declared dynamic-extent
. The dynamic-extent
declarations are not verified, but are simply trusted; if the
constraints in the Common Lisp standard are violated, the best that
can happen is for the program to have garbage in variables and return
values; more commonly, the system will crash.
As a consequence of this, the condition for performing stack
allocation is stringent: either of the speed
or space
optimization qualities must be higher than the maximum of
safety
and debug
at the point of the allocation. For
example:
(locally (declare (optimize speed (safety 1) (debug 1))) (defun foo (&rest rest) (declare (dynamic-extent rest)) (length rest)))
Here the &rest
list will be allocated on the stack. Note that
it would not be in the following situation:
(defun foo (&rest rest) (declare (optimize speed (safety 1) (debug 1))) (declare (dynamic-extent rest)) (length rest))
because both the allocation of the &rest
list and the variable
binding are outside the scope of the optimize
declaration.
There are many cases when dynamic-extent
declarations could be
useful. At present, SBCL implements
&rest
lists, where these are declared
dynamic-extent
.
list
and list*
, whose result is
bound to a variable, declared dynamic-extent
, such as
(let ((list (list 1 2 3))) (declare (dynamic-extent list) ...))
or
(flet ((f (x) (declare (dynamic-extent x)) ...)) ... (f (list 1 2 3)) ...)
make-array
, whose result is
bound to a variable, declared dynamic-extent
. The resulting
array should be one-dimensional, the only allowed keyword argument is
:element-type
.
Notice, that stack space is limited, so allocation of a large vector may cause stack overflow and abnormal termination of the SBCL process.
flet
or
labels
with a bound declaration dynamic-extent
.
Closed-over variables, which are assigned (either inside or outside
the closure) are still allocated on the heap. Blocks and tags are also
allocated on the heap, unless all non-local control transfers to them
are compiled with zero safety
.
Future plans include
dynamic-extent
;
list
, list*
and cons
(including following chains during initialization, and also for
binding mutation), where the allocation is declared
dynamic-extent
;
&rest
list, even when this is not declared
dynamic-extent
;
dynamic-extent
.