On Sun, Mar 28, 2010 at 1:55 PM, Nikodemus Siivola <nikodemus@random-state.net> wrote:
On 24 March 2010 15:16, Nikodemus Siivola <nikodemus@random-state.net> wrote:

> Attached is my first cut, which makes
> (defun baz (x) (unwind-protect (setf x (quux x)) (setf x (quux x))))
> non-consing. Unless I discover something terribly wrong about this, I
> will commit this as 1.0.37.something-small.

Something terribly wrong:

(defun quux (x) (list :quux x))
(defun cleanup (x) (list :cleanup x))
(defun baz (x)
 (unwind-protect (setf x (quux x))
   (setf x (cleanup x)))
(baz t) ; => (:QUUX T) should be (:cleanup (:quux t))

Cleanups are not in the same frame as the protected forms.

So, it turns out that what's happening here is that the compiler is generating a KNOWN-CALL-LOCAL, which does, in fact, spawn a new stack frame. At the same time, the UNWIND assembler-routine is preserving the frame pointer (the current-cont slot of the catch-block structure), which allows the backtrace to show the cleanup-fun being called by the frame containing the UWP.  Nikodemus: The smoking gun is in my annotation to your paste 96988.

 -- Nikodemus

-- Alastair