|
Suggestion: ephemeron-case
Daphne Preston-Kendal
(04 Feb 2025 10:08 UTC)
|
||
|
Re: Suggestion: ephemeron-case
John Cowan
(04 Feb 2025 11:35 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Vincent Manis (he/him)
(04 Feb 2025 19:38 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Marc Nieper-Wißkirchen
(05 Feb 2025 15:12 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Daphne Preston-Kendal
(05 Feb 2025 15:30 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Marc Nieper-Wißkirchen
(05 Feb 2025 18:04 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Daphne Preston-Kendal
(05 Feb 2025 18:16 UTC)
|
||
|
(missing)
|
||
|
Fwd: Suggestion: ephemeron-case
Marc Nieper-Wißkirchen
(16 Mar 2025 13:19 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Marc Nieper-Wißkirchen
(12 May 2025 11:51 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Arthur A. Gleckler
(10 Jun 2025 23:16 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Daphne Preston-Kendal
(03 Aug 2025 09:38 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Marc Nieper-Wißkirchen
(03 Aug 2025 15:29 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Marc Nieper-Wißkirchen
(03 Aug 2025 15:30 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Daphne Preston-Kendal
(09 Oct 2025 12:34 UTC)
|
||
|
Re: Suggestion: ephemeron-case
Marc Nieper-Wißkirchen
(09 Oct 2025 13:24 UTC)
|
||
|
Usefulness of reference-barrier
Daphne Preston-Kendal
(12 Oct 2025 20:16 UTC)
|
||
|
Re: Usefulness of reference-barrier Marc Nieper-Wißkirchen (13 Oct 2025 05:58 UTC)
|
||
|
Re: Usefulness of reference-barrier
Marc Nieper-Wißkirchen
(13 Oct 2025 07:21 UTC)
|
||
|
Re: Usefulness of reference-barrier
Marc Nieper-Wißkirchen
(13 Oct 2025 11:17 UTC)
|
||
|
Re: Usefulness of reference-barrier
Marc Nieper-Wißkirchen
(22 Oct 2025 07:18 UTC)
|
||
|
Re: Usefulness of reference-barrier
Daphne Preston-Kendal
(30 Oct 2025 22:46 UTC)
|
||
|
Re: Usefulness of reference-barrier
Marc Nieper-Wißkirchen
(31 Oct 2025 07:50 UTC)
|
||
|
Re: Usefulness of reference-barrier
Daphne Preston-Kendal
(30 Oct 2025 23:03 UTC)
|
||
|
Re: Usefulness of reference-barrier
Marc Nieper-Wißkirchen
(31 Oct 2025 08:02 UTC)
|
||
|
Re: Usefulness of reference-barrier
Marc Nieper-Wißkirchen
(04 Nov 2025 18:57 UTC)
|
||
Can you state precisely what you mean by forbidden certain reorderings?
Allowing or preventing reordering an expression makes only sense with
respect to other expressions. For example, reordering of expressions
that write to a port is forbidden with respect to other procedures
writing to the same port. Now, if we declare that reads or writes to
the store must not be reordered around some expression (like a call to
ephemeron-key), this will be extremely costly (because, conceptually,
every variable reference is a read or write to the store) and is not
what compilers do in practice. The following example if for Chez:
> (expand/optimize '
(lambda (f g)
(let ((v (vector 1 2)))
(f v)
(let ((w (g v)))
(boolean=? (vector? v) (vector? w))))))
(lambda (f g)
(let ([v (#2%vector 1 2)])
(f v)
(#3%boolean=? #t (#2%vector? (g v)))))
The argument F can be thought of as a procedure storing V as a key to
some ephemeron (e.g., as part of some weak table). The argument G can
be thought of as a procedure returning the previously stored key (if
still stored) or #f, otherwise. In the source code, the location of V
in the store is accessed after G is called, so with naive semantics
"do not reorder anything", the value of V is still alive after the
call to G, so G should return the key.
In the optimized version, however, cp0 replaces the constant
expression involving V with the constant (#t in this case). If a
garbage collection is going on during the evaluation of the call to F
or G, G will no longer return the previously stored key.
This example also demonstrates that "reordering" is not some fancy
optimisation pass that can easily be turned on or off, but the basis
of a number of undisputed basic optimisations.
The reason why code seems to work without "reference-barrier" is that
failure due to leaving it out is even more sporadic and subtle than
failure due to missing synchronisation in concurrent code (see C's
<stdatomic.h>, for example).
Now, ephemerons are supposed to be a relatively low-level interface on
which library writers can build high-level data structures. Calls to
reference-barrier will usually be hidden in the implementation. See
the example code in the new draft, where the documentation for
weakmap-contains? and weakmap-ref clearly says that the key will be
kept alive.
Likewise, convenience procedures like
ephemeron-ref EPH KEY DEFAULT
defined by
(define (ephemeron-ref eph key default)
(let ((val (if (eq? (ephemeron-key eph) key) (ephemeron-value eph) default)))
(reference-barrier key)
val))
are possible (and should/could go into some convenience library built
on top of the primitives in SRFI 254).
Taylor Campbell posted more on the SRFI 124 mailing list; he also says
that the low-level interface to ephemerons won't be reliable without
reference-barrier, expressed by a simple "can't":
https://srfi-email.schemers.org/srfi-124/msg/4182299/
JavaScript has solved the problem differently (and thus does not need
reference-barrier). Quoting from MDN:
"If your code has just created a WeakRef for a target object, or has
gotten a target object from a WeakRef's deref method, that target
object will not be reclaimed until the end of the current JavaScript
job (including any promise reaction jobs that run at the end of a
script job). That is, you can only "see" an object get reclaimed
between turns of the event loop. This is primarily to avoid making the
behavior of any given JavaScript engine's garbage collector apparent
in code — because if it were, people would write code relying on that
behavior, which would break when the garbage collector's behavior
changed. (Garbage collection is a hard problem; JavaScript engine
implementers are constantly refining and improving how it works.)"
In other words, there are implicit reference barriers at the end of
each job, meaning that reclaiming weakly-held objects is coarse. This
is less of a problem in JavaScript because jobs are supposed to be
short-running. This does not apply to Scheme.
Marc
Am So., 12. Okt. 2025 um 22:16 Uhr schrieb Daphne Preston-Kendal
<xxxxxx@nonceword.org>:
>
> On 9 Oct 2025, at 15:24, Marc Nieper-Wißkirchen <xxxxxx@gmail.com> wrote:
>
> > Thank you for the example code. Unfortunately, the suggested
> > definition of "ephemeron-case" is useless.
>
> I’d like to take this conversation in a slightly different direction.
>
> Can you offer any demonstration at all – from any real language runtime you can think of, Scheme or non-Scheme – that reference-barrier is actually needed; that compilers without it would break things in the way you say they could when dereferencing weak pointers; that compilers which would do the ‘optimization’ you invented reference-barrier to productively frustrate would not be completely broken by design?
>
> I cannot find any.
>
> Chez Scheme added keep-live in version 10, but it had ephemerons and other weak references long before. Its documentation suggests the purpose of keep-live is related to the ‘immobile objects’ feature, not to the re-ordering optimization you are concerned about.
>
> MIT Scheme seems to have added reference-barrier purely because of SRFI 124. It also had ephemerons and weak pairs before. Riastradh suggested reference-barrier: his rationale appears to have been entirely different, to do with an implementation where broken ephemerons were replaced by #f. <https://srfi-email.schemers.org/srfi-124/msg/2905901/>
>
> Outside of the Scheme world, I am unable to find any language or implementation of any language which has anything like reference-barrier. JavaScript’s ephemeron tables (WeakMap) and weak sets (WeakSet) and weak boxes (WeakRef) all have no such concept. OCaml, in runtime semantics a close match to Scheme, doesn’t have it. <https://ocaml.org/manual/5.3/api/Ephemeron.html> Even Haskell, which due to its lazy evaluation is extremely reordering-happy in its implementation, does not appear to have an equivalent of the reference-barrier. <https://hackage.haskell.org/package/base-4.21.0.0/docs/System-Mem-Weak.html>
>
> I haven’t surveyed Scheme implementers (well, except Alex Shinn who made his feelings known well enough when it came up in another context), but I suspect this whole idea of yours is premature pessimization. Compilers are quite intelligent enough to realize that ephemeron-key and ephemeron-datum themselves are procedures that can’t safely be re-ordered around – and this is not a ‘sufficiently smart compiler’ argument, because a truly dumb compiler wouldn’t have an issue here either, since the problem is that you’re arguing a compiler might attempt to be smart but do something wrong. In reality, a compiler which tries to be smart in that way would simply be broken, and the way it would be broken would be the same as if it allowed re-ordering set! or write or any other side-effectual procedure so the side-effects happen in the wrong order. They already have mechanisms that tell them they can’t do that, and if they can apply those mechanisms to reference-barrier, they can just as well apply them to the actual source of the reference instead.
>
> [Not speaking as chair but as an individual WG2 member:] If reference-barrier stays in the SRFI up to finalization and thus remains a candidate for R7RS large, I will want a comprehensive survey of implementers on this question before we clutter the Scheme report with it.
>
> Best wishes
>
>
> Daphne
>