[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Issue: STACK-LET (Version 1)
Edit history: 27-Jun-88, Version 1 by Pitman
Status: For Internal Discussion
Sometimes a programmers knows that a particular data structure
will have only dynamic extent. In some implementations, it is
possible to allocate such structures in a way that will make them
easier to reclaim than by general purpose garbage collection
(eg, on the stack or in some temporary area). Currently, however,
there is no way to request the use of such an allocation mechanism.
Introduce the new macros:
STACK-LET bindings &BODY forms [Macro]
STACK-LET* bindings &BODY forms [Macro]
Like LET and LET*, but the objects which are the initial
values of the variables in the binding list have only
For each initial binding, the form is macroexpanded (as if
by MACROEXPAND-1) until either no further macro expansion is
possible or a form which is recognized by STACK-LET is seen.
(CONS x y) permits STACK-LET to allocate a cons on the stack.
(LIST x y z) permits STACK-LET to allocate a list on the stack.
(LIST* x y z) permits the first two conses of the resulting
list to be allocated on the stack.
(MAKE-ARRAY ...) permits an array to be allocated on the stack.
(MAKE-xxx ...) where MAKE-xxx is a defstruct constructor permits
the structure type to be allocated on the stack.
Note that an initial value form of (LIST X Y) is not the same
as (CONS X (LIST Y)) since STACK-LET may arrange for two cells
of the former to be stack-allocated, and only one cell of the
latter (the one created by CONS).
Note further that in (LIST (LIST 1 2) 3), only the top level
list (the one containing a cons and 3) may be stack allocated.
The list (1 2) must be allocated normally.
It is always permissible for STACK-LET to behave like LET.
Its use is merely advice to an implementation about the use
of a variable which might not otherwise be provable.
(STACK-LET ((X (LIST 1 2 3)))
prints (1 2 3)
It permits a programmer to offer advice to an implementation about
what may be stack-allocated for efficiency.
It may be difficult or impossible for a compiler to infer this
same information statically.
Since a number of implementations offer this capability and there
is demand from users for access to the capability, this ``codifies
Symbolics Genera and Symbolics Cloe offer this extension.
Cost to Implementors:
No cost is forced since implementations are permitted to treat
STACK-LET and STACK-LET* as LET and LET*, respectively.
Cost to Users:
None. This change is upward compatible.
Cost of Non-Adoption:
Some portable code would be forced to run more slowly (due to
GC overhead), or to use non-portable primitives.
The cost of non-adoption is avoided.
This primitive allows a fairly low level optimization to work
by asking the user to provide only very high level information.
The alternatives (sharpsign conditionals, some of which may
lead to more bit-picky abstractions) are far less aesthetic.
It would also be possible to unify this proposal with
REST-ARGUMENT-EXTENT. The technique would be to allow
(LET ((X (LIST ...)))
(DECLARE (DYNAMIC-EXTENT X))
to be rewritten by the compiler as:
(SYSTEM::STACK-LET ((X (LIST ...)))
Pitman supports the STACK-LET:NEW-MACROS.
A better name might be chosen, but since some existing dialects
use this name, the name STACK-LET was suggested in an attempt to
not be gratuitously incompatible. (Also, the name DYNAMIC-LET,
which might seem more intuitive, is in use in other dialects to
mean that a dynamic variable is being bound, not that a lexical
variable is being bound to a dynamic object. It might, therefore,
be confusing to recycle that name here.)