From: Viktor Winschel
Subject: how to get deeper trace in cmucl+slime ?
Date: 
Message-ID: <es99sj$kgd$1@news.BelWue.DE>
Hi,

I am using CMUCL with Slime on a Debian-sarge box
and the trace does not show all calls:

-------------------------------------------------
CL> (defun fact (n)
	(if (<= n 1) 1
		(* n (fact (- n 1))))
FACT
CL> (trace fact)
T
CL> (fact 4)
  0: (FACT 4)
  0: FACT returned 24
24
CL>
-------------------------------------------------

Is there a way to change that?

thanx
Viktor

From: Joel Wilsson
Subject: Re: how to get deeper trace in cmucl+slime ?
Date: 
Message-ID: <1172845578.914280.99920@j27g2000cwj.googlegroups.com>
On Mar 2, 2:47 pm, Viktor Winschel <········@rumms.uni-mannheim.de>
wrote:
> CL> (trace fact)
> T
> CL> (fact 4)
>   0: (FACT 4)
>   0: FACT returned 24
> 24
> CL>

It's clever enough to figure out how to make it tail-recursive,
so it really is only called called once; the rest is done through
simple iteration instead of by doing costly function calls.

> Is there a way to change that?

Yes, use (declare (optimize (debug 3)))

Regards,
  Joel
From: Rainer Joswig
Subject: Re: how to get deeper trace in cmucl+slime ?
Date: 
Message-ID: <joswig-FDFC4C.15543102032007@news-europe.giganews.com>
In article <·······················@j27g2000cwj.googlegroups.com>,
 "Joel Wilsson" <············@gmail.com> wrote:

> On Mar 2, 2:47 pm, Viktor Winschel <········@rumms.uni-mannheim.de>
> wrote:
> > CL> (trace fact)
> > T
> > CL> (fact 4)
> >   0: (FACT 4)
> >   0: FACT returned 24
> > 24
> > CL>
> 
> It's clever enough to figure out how to make it tail-recursive,
> so it really is only called called once; the rest is done through
> simple iteration instead of by doing costly function calls.

Are you sure that's the reason?
The code is not tail-recursive.

I'd guess that the TRACE worked for calls of the global FACT
function but not for local recursive calls. Increasing
the debug level and recompiling FACT might help.


> 
> > Is there a way to change that?
> 
> Yes, use (declare (optimize (debug 3)))
> 
> Regards,
>   Joel
From: Joel Wilsson
Subject: Re: how to get deeper trace in cmucl+slime ?
Date: 
Message-ID: <1172849918.779027.193370@z35g2000cwz.googlegroups.com>
On Mar 2, 3:54 pm, Rainer Joswig <······@lisp.de> wrote:
>  "Joel Wilsson" <············@gmail.com> wrote:
> > It's clever enough to figure out how to make it tail-recursive,
> > so it really is only called called once; the rest is done through
> > simple iteration instead of by doing costly function calls.
>
> Are you sure that's the reason?
> The code is not tail-recursive.

I'm using SBCL, but the optimized assembler code has only one CALL,
and that's to GENERIC-*

On the other hand, the unoptimized code has:
;      6D6:       8B05F4D5814A     MOV EAX, [#x4A81D5F4]
                         ; #<FDEFINITION object for FACT-UNOPTIMIZED>
and then does:
;      6F5: L3:   FF5005           CALL DWORD PTR [EAX+5]

I wouldn't bet my life on it but I'm reasonably sure that yes,
that's the reason.

> I'd guess that the TRACE worked for calls of the global FACT
> function but not for local recursive calls. Increasing
> the debug level and recompiling FACT might help.

Err, well, unless there's tail-call optimizations going on
there's no difference from the call inside the function from
calls from outside the function, so why would it work for
global calls but not recursive calls?

Regards,
  Joel
From: Rainer Joswig
Subject: Re: how to get deeper trace in cmucl+slime ?
Date: 
Message-ID: <joswig-B3F7FC.16555702032007@news-europe.giganews.com>
In article <························@z35g2000cwz.googlegroups.com>,
 "Joel Wilsson" <············@gmail.com> wrote:

> On Mar 2, 3:54 pm, Rainer Joswig <······@lisp.de> wrote:
> >  "Joel Wilsson" <············@gmail.com> wrote:
> > > It's clever enough to figure out how to make it tail-recursive,
> > > so it really is only called called once; the rest is done through
> > > simple iteration instead of by doing costly function calls.
> >
> > Are you sure that's the reason?
> > The code is not tail-recursive.
> 
> I'm using SBCL, but the optimized assembler code has only one CALL,
> and that's to GENERIC-*

Right. But FACT needs to be in tail position. Not *.

You will see SBCL blowing the control stack if you
give FACT a large argument.

> 
> On the other hand, the unoptimized code has:
> ;      6D6:       8B05F4D5814A     MOV EAX, [#x4A81D5F4]
>                          ; #<FDEFINITION object for FACT-UNOPTIMIZED>
> and then does:
> ;      6F5: L3:   FF5005           CALL DWORD PTR [EAX+5]
> 
> I wouldn't bet my life on it but I'm reasonably sure that yes,
> that's the reason.

It's calling itself. It is a local recursive call.

Write FACT as a tail-recursive version and compiler/disassemble
again.

> 
> > I'd guess that the TRACE worked for calls of the global FACT
> > function but not for local recursive calls. Increasing
> > the debug level and recompiling FACT might help.
> 
> Err, well, unless there's tail-call optimizations going on
> there's no difference from the call inside the function from
> calls from outside the function, so why would it work for
> global calls but not recursive calls?

There is a difference. Global calls to FACT are going through
the symbol function cell (unless it is optimized, which is
also possible). Local functions calls usually don't.

See for example the CMUCL documentation:

http://common-lisp.net/project/cmucl/doc/cmu-user/debugger.html#toc110

See for example this sentence:

"Note that if you trace using :encapsulate, you will only get a
trace or breakpoint at the outermost call to the traced
function, not on recursive calls."

This is a typical speed/debugging tradeoff you see in compiled
Lisp systems.

> 
> Regards,
>   Joel
From: Joel Wilsson
Subject: Re: how to get deeper trace in cmucl+slime ?
Date: 
Message-ID: <1172852030.069353.323370@v33g2000cwv.googlegroups.com>
On Mar 2, 4:55 pm, Rainer Joswig <······@lisp.de> wrote:
> Right. But FACT needs to be in tail position. Not *.
>
> You will see SBCL blowing the control stack if you
> give FACT a large argument.

Yes, I stand corrected. I thought the compiler had some clever
transform to turn it into a properly tail recursive form, but
I see now it doesn't.

> It's calling itself. It is a local recursive call.
>
> Write FACT as a tail-recursive version and compiler/disassemble
> again.

Done, and I see what you mean. I wasn't looking closely enough at
the output of (disassemble 'fact-optimized) before, now that I
compare it with fact-tail I see that it's subtracting from the
stack pointer while fact-tail does not.

I think I learned something! :)

Thanks,
  Joel
From: Vassil Nikolov
Subject: Re: how to get deeper trace in cmucl+slime ?
Date: 
Message-ID: <yy8vslcmy7k7.fsf@eskimo.com>
On Fri, 02 Mar 2007 16:55:57 +0100, Rainer Joswig <······@lisp.de> said:
| ...
| There is a difference. Global calls to FACT are going through
| the symbol function cell (unless it is optimized, which is
| also possible). Local functions calls usually don't.

  ... which is what this sentence from chapter 25 (I think) of CLtL2
  is about, which says that within the body of a function, the compiler
  may assume that a call to a function of the same name is a call to the
  same function.  (I know I shouldn't be quoting CLtL2, but I am pretty
  sure the HyperSpec has the equivalent statement in the section on
  compilation.)

  ---Vassil.

-- 
mind mate, n.
  One of two persons mentally compatible with each other (cf. soul mate).
From: Raymond Toy
Subject: Re: how to get deeper trace in cmucl+slime ?
Date: 
Message-ID: <sxd4pp34mva.fsf@rtp.ericsson.se>
>>>>> "Viktor" == Viktor Winschel <········@rumms.uni-mannheim.de> writes:

    Viktor> Hi,

    Viktor> I am using CMUCL with Slime on a Debian-sarge box
    Viktor> and the trace does not show all calls:

    Viktor> -------------------------------------------------
    CL> (defun fact (n)
    Viktor> 	(if (<= n 1) 1
    Viktor> 		(* n (fact (- n 1))))
    Viktor> FACT

Tracing the interpreter doesn't work too well.  (It should be made
better.)

But if you compile the code, tracing works better:

CL-USER> (compile 'fact)
; Compiling LAMBDA (N): 
; Compiling Top-Level Form: 
FACT
NIL
NIL
CL-USER> (trace fact)
(FACT)
CL-USER> (fact 4)
  0: (FACT 4)
    1: (FACT 3)
      2: (FACT 2)
        3: (FACT 1)
        3: FACT returned 1
      2: FACT returned 2
    1: FACT returned 6
  0: FACT returned 24
24


Ray