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

Re: constant folding/smashing

I believe there are 3 places in CLtL where "constant objects",
"constant values", and "constants in code" are discussed:
   DEFCONSTANT	pgs. 68-69
   EQ		pg. 78
   QUOTE	pg. 86
   [Any others?]

What do these sections explicitly state about what is actually being
held constant and what can still be modified?

The DEFCONSTANT section, pgs. 68-69, explicitly allows "constant
folding" (i.e., "replac[ing] references to the name of the constant by
the value of the constant").  In this case, it is clear the the
value-cell of DEFCONSTANT's first argument (a symbol) is held

But it does not state that any of the symbol's other `components' are
held constant.  E.g., Can that symbol's function-cell or plist or
home-package be modified? I believe most implementations correctly
infer the answer to be "YES".

Pgs. 68-69 also do not state whether or not the object contained in
the constant's value-cell may have its components modified (assuming
it is a composite object)?  I.e., Is the value itself held constant?
I'm not sure how most implementations have decided this, but I am sure
that the DEFCONSTANT section does not authorize it (even implicitly).

In the EQ section, pg. 78, "constant collapsing" is explicitly
allowed.  This is not the same thing as "constant folding" (For
a while I thought it was.)  Constant folding means replacing a name by
its value (an object).  Constant collapsing means replacing 2 or more
"constants in code to be compiled" that are EQUAL but not EQ with a
single one of those objects.

What is a "constant in code to be compiled?"  An answer to this
question is given on pg. 78: "An object is considered to be a constant
in code to be compiled if it is a self-evaluating form or is contained
in a QUOTE form."  This does not seem to allow constant collapsing of
the values of DEFCONSTANTs.  I think this is an oversight, since pg.
69 allows the compiler to "replace references ... by the value of the
constant ... in order to allow further optimizations [e.g., constant

So far, we have seen two types of `constant assumption/optimization'
explicity permitted: constant folding and constant collapsing.
Neither has suggested the optimization/assumption that a composite
object may be made `Read-Only'.

What about pg. 86, the section on QUOTE.  Unfortunately, QUOTE muddies
the waters by using such phrases as "constant data object", "constant
object", and "constant value".  It is my contention though, that these
phrases imply nothing more than the longer phrase "constant in code"
and do NOT imply that the data object itself is held to be constant.

I contend that the QUOTE special form is nothing more than a way of
providing an `anonymous DEFCONSTANT', i.e., a form that is guaranteed
to return the same (i.e, EQ) value EVERY time.  For example, the
following DEFUN of FOO using QUOTE

  (IF (< -1 N (LENGTH (QUOTE (1 2 3))))
    (ELT (QUOTE (1 2 3)) N)

is semantically equivalent to the following DEFUN using an `anonymous

    (IF (< -1 N (LENGTH #1#))
      (ELT #1# N)

It is this aspect of `constant'ly returning the same (EQ) object that
is meant in the sentence on pg. 86: "[QUOTE] allows any Lisp object to
be written as a constant value in a program."  It is the value of the
(QUOTE ...) form that is held constant, not the object itself.  The
same (EQ) object will always be referenced, but that object may be
modified over time (if it is a composite object).

Thus, I believe that the practice of collapsing an object that is a
"constant in code to be compiled" with an EQUAL object in Read-Only
space is not authorized by CLtL, even implicitly.  Moreover, I think
that the practice of collapsing an object that is a "constant in code
to be compiled" with an EQUAL object in Read-Only space is a bad idea,
since it violates the Consistency requirement between compiler and
interpreter.  When learning/experimenting-with Lisp at Top-Level,
people regularly type in forms such as
   (setf (first '(1 2 3)) 'a)
which won't work if quoted objects are collapsed into Read-Only
space.  Also it is hard to understand why
   (setf (elt '"abc" 0) #\A)
is illegal
   (setf (elt '#(#\a #\b #c) 0) #\A)
is not. (You can't collapse the general array to Read-Only space since for
it to be EQUAL it must be EQ!  This is why
   (setf (symbol-plist 'X) '())
doesn't cause a memory violation.)

In summary, CLtL explicitly permits two constant optimizations:
folding and collapsing.  But it says nothing (as far as I have found)
about what would permit an object to be put into Read-Only space,
i.e., to be made unmodifiable.

-- Nick