[gambit-list] Re --enable-auto-forcing: Scope, how/where implemented, how build (with) it properly?

Adam adam.mlmb at gmail.com
Mon Sep 18 15:07:15 EDT 2017

Hi Marc,

Thank you very much for clarifying.

Three brief followup questions at the bottom (marked 1. 2. 3.).

2017-09-18 23:55 GMT+08:00 Marc Feeley <feeley at iro.umontreal.ca>:

> > Also.. if I understand you right, there are cases when Gambit with
> auto-forcing enabled also would fail evaluating (abs (delay 0)) .
> With --enable-auto-forcing, this case works only when abs is not inlined,
> in other words an actual function call to abs is performed (because the
> library definition correctly forces the argument).  This can be achieved in
> various ways, like (declare (not run-time-bindings abs)) or (declare
> (standard-bindings) (not inline-primitives abs)).
> This needs to be fixed so that those declarations, which typically improve
> execution speed, can be used reliably in a system built with
> --enable-auto-forcing.

Ahaa, so that is a limit that exists currently for --enable-auto-forcing .
Thanks for pointing out!


> Also, when using the default (declare (safe)) the compiler converts (car
> lst) into
>     (if (##pair? lst) (##car lst) (car lst))
> rather than the correct
>     (let ((lst (##force lst)))
>       (if (##pair? lst) (##car lst) (car lst)))

This was just another iteration of what you said already in the section
above right?


> > > Would it be possible for me to disable this particular aspect of the
> auto-forcing, to get higher performance?
> >
> > Currently auto-forcing only works in interpreted code.  So if your
> program does (f x) and (car y) and you compile that, then “f” will not be
> forced and “y” will not be forced if car is inlined, for example if you
> (declare (not safe)).  You can consider this a bug… to be fixed.
> Actually this is not quite true… f will be forced in the call (f x)

[also in compiled mode -  3. I interpret you to mean that here, that is
correct, right?]

thanks to this definition in lib/_kernel.scm:
> (define-prim (##apply-with-procedure-check oper args)
>   (##declare (not interrupts-enabled))
>   (macro-force-vars (oper)
>     (if (##procedure? oper)
>       (##apply oper args)
>       (##raise-nonprocedure-operator-exception oper args #f #f))))
Wait, what does |##apply-with-procedure-check| actually do, in what
situations is it invoked, is this run on all (f a1 a2 ...) with oper = f
and args = (list a1 a2 ...) for any procedure call made anywhere, when
compiling with (declare (safe))?

1. So if I just remove the |macro-force-vars| in there, |f| will not be
forced in compiled mode?

2. Just if it is possible, is there some easy way to make also |f| *not* be
forced in compiled mode?

Not forcing |f| ever, would be useful in situations where you use the
auto-forcing only to force data structures but never any code.

I hypothesize that this will provide significant speed increases.

Will test and benchmark following your next clarification.

Thanks a lot!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20170919/87e8e47f/attachment.htm>

More information about the Gambit-list mailing list