From: Paul Khuong on
In article <821vh3uayw.fsf(a)netfonds.no>,
"Frode V. Fjeld" <frode(a)netfonds.no> wrote:

> Pascal Costanza <pc(a)p-cos.net> writes:
>
> > [...] The problem that causes this is that the dynamic-extent
> > declaration in 'caller doesn't reach only the list that makes up the
> > &rest args, but also the list created in 'test - the HyperSpec states
> > that dynamic-extent declarations cover everything directly or
> > indirectly reachable that is not 'otherwise accessible', and since the
> > list created in 'test is freshly consed, it is indeed not 'otherwise
> > accessible' at the time 'caller is invoked.
>
> FWIW the sbcl behavior as you describe it I find unreasonable. I would
> say that the fresh list is in fact "otherwise accessible" as the
> returned value of the function call. The list is clearly "accessible" as
> (presumably) it's this access that causes your sbcl to crash, and it's
> "otherwise", i.e. not in any sense by going through the binding that was
> declared dynamic-extent.

No. At the time the &rest list is bound, everything it contains is
"otherwise accessible". Just as you'd blame the user who did

(let ((x ...))
(declare (dynamic-extent x))
x)

the same logic applies to

(let ((x (list (cons ...) ...)))
(declare (dynamic-extent x))
(first x))

The point of the dynamic extent declaration is obviously not to allow
the compiler to perform transparent escape analysis, which is what you
propose (to consider values that escape despite d-x declarations as
"otherwise accessible"). Rather, it is a guarantee that whatever the
dynamic extent variable x is bound to will never escape, and that the
same is true for values that, at the time x is bound, are only
accessible through the datum bound to x. The virality of dxness is a
simple consequence of (e.g.) our desire for dynamic-extent lists to be
fully stack allocated, and not just the first cons (which is, after all,
what x is bound to; the rest is just an accident). It's only symmetry to
apply the same logic to cons graphs, and not just lists, and then to
arbitrary objects.

In the second example above, the first time x is bound, the cons to
which x is bound is otherwise inaccessible (trivially, every reference
to that cons must pass through that very cons), but so are the rest of
the list and the first element in the list (again, every path to these
data must go through the *cons* that is bound to x).

Paul Khuong
From: Pascal Costanza on
On 02/02/2010 16:11, Paul Khuong wrote:

> The virality of dxness is a
> simple consequence of (e.g.) our desire for dynamic-extent lists to be
> fully stack allocated, and not just the first cons (which is, after all,
> what x is bound to; the rest is just an accident).

Thanks a lot for this sentence, this makes it very clear why the
HyperSpec specifies it like it does. I guess this was the explanation I
was looking for, so thanks indeed.


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Alessio Stalla on
On Feb 2, 11:47 am, Pascal Costanza <p...(a)p-cos.net> wrote:
> Hi,
>
> I recently submitted a report to the SBCL devel mailing list about what
> I believed to be a bug in their compiler, only to learn that my
> understanding of what dynamic-extent declarations do was just wrong.
>
> Here is the example:
>
> (defun definer (x)
>    (list x))
>
> (declaim (inline caller))
>
> (defun caller (&rest args)
>    (declare (dynamic-extent args)
>             (optimize (speed 3) (debug 0) (safety 0)
>                       (compilation-speed 0)))
>    (apply #'definer args))

Here is the problem: (apply #'definer args) is the return value of the
caller, but it shares structure with args, which has been declared
dynamic-extent. You should copy-tree the return value to be safe.

> (defun test ()
>    (caller (list 0)))
>
> If I run test in SBCL, I get the following output:
>
> ((SB-INT:STREAM-ENCODING-ERROR))
>
> ...or worse. The problem that causes this is that the dynamic-extent
> declaration in 'caller doesn't reach only the list that makes up the
> &rest args, but also the list created in 'test - the HyperSpec states
> that dynamic-extent declarations cover everything directly or indirectly
> reachable that is not 'otherwise accessible', and since the list created
> in 'test is freshly consed, it is indeed not 'otherwise accessible' at
> the time 'caller is invoked.
>
> This screws up my mental model of the dynamic-extent declaration that I
> had, and I currently have problems coming up with a better mental model
> of when and how to use it. At the moment it seems to me that
> dynamic-extent declarations can be too 'aggressive' to the extent that I
> don't know what guarantees I can and cannot give to users of my libraries..
>
> Does this mean that I cannot use dynamic-extent at all? Or only deep
> down in the call chain of functions that are not exported to the
> outside? When and how do other people use dynamic-extent? What's a good
> rule of thumb here?
>
> Help! :)
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/

From: Tim Bradshaw on
On 2010-02-02 14:00:57 +0000, Pascal Costanza said:

> There should be a 'shallow dynamic-extent' declaration that doesn't
> reach out for objects allocated at the call site...

Does this happen when the function is not declared inline?

From: Pascal J. Bourguignon on
Tim Bradshaw <tfb(a)tfeb.org> writes:

> On 2010-02-02 14:00:57 +0000, Pascal Costanza said:
>
>> There should be a 'shallow dynamic-extent' declaration that doesn't
>> reach out for objects allocated at the call site...
>
> Does this happen when the function is not declared inline?

Yes, inlineness is irrelevant here.

--
__Pascal Bourguignon__
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9 10
Prev: online shopping
Next: python admin abuse complaint