[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Issue: STACK-LET (Version 1)



Issue:          STACK-LET
References:     None
Category:       ADDITION
Edit history:   27-Jun-88, Version 1 by Pitman
Related-Issues: REST-ARGUMENT-EXTENT
Status:	        For Internal Discussion

Problem Description:

  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.

Proposal (STACK-LET:NEW-MACROS):

  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
    dynamic extent.

    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.

    For example:

    (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.

Test Case:

  (STACK-LET ((X (LIST 1 2 3)))
    (PRINT X)
    NIL)
  prints (1 2 3)

Rationale:

  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
  existing practice.''

Current Practice:

  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.

Benefits:

  The cost of non-adoption is avoided.

Aesthetics:

  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.

Discussion:

  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 ...)))
     ...)
  for example.

  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.)