Rebooting the __metada/__mutable discussion
RazvanN
razvan.nitu1305 at gmail.com
Wed Apr 6 09:41:52 UTC 2022
Hello everyone,
Lately, I've been looking at the __metadata/__mutable
discussions. For reference, here is the material I have so far:
1. Forum discussion:
https://forum.dlang.org/thread/3f1f9263-88d8-fbf7-a8c5-b3a2a5224ce0@erdani.org?page=1
2. Timon's original DIP:
https://github.com/RazvanN7/DIPs/blob/Mutable_Dip/DIPs/timon_dip.md
3. My updated DIP which is based on Timon's:
https://github.com/RazvanN7/DIPs/blob/Mutable_Dip/DIPs/DIP1xxx-rn.md
We need this to be able to implement generic reference counting.
So our main
problem is how do we reference count immutable/const objects.
Timon's original
proposal tried to implement __metadata in a way that does not
affect purity
based optimizations. I think that this could be done:
1. A strongly pure function (that return types without
indirections) will return the same result when applied to the
same immutable arguments.
Fixed by rewritting
```d
auto a = foo(arg) // foo -> strongly pure
aubo b = foo(arg)
````
to
```d
auto a = foo(arg)
auto b = a
```
This is taken from Timon DIP.
2. The set of references returned from strongly pure functions
can be safely converted to immutable or shared.
This is no affected by the introduction of __metadata.
3. A strongly pure function whose result is not used may be
safely elided.
```d
struct S{
private int __metadata x;
}
void foo(immutable ref S s)pure{
s.x += 1;
}
void main(){
immutable S s;
foo(s); // there is no reason for this call to happen
assert(s.x==1); // can't rely on this, it might also be 0
}
```
Essentially, if `foo` is strongly pure, then the compiler can
optimize away
the call to it and your reference count is blown away. If we look
at it this
way, the problem seems to be unsolvable. However, the idea of
__metadata is to
be used solely by library developers and even they should take
extra care.
As such, I would propose that `__metadata` can only be accessed
from inside
the aggregate that defines it (`private` here means `Java
private`) and methods
that access __metadata directly need to also private. I think
that this makes sense since the reference is updated only when
you call the copy constructor and the assignment operator. These
methods should be public and they can call the incRef, decRef
that are mandatory private. This way, it becomes impossible to
access a `__metadata` field without going through the object
methods. This makes sense, since the object is the only one that
should manage the `__metadata`.
Now, if we do it like this, then `foo` will not have any means of
accessing `x`
apart from assigning s, passing s to a function or copy
constructing from s.
However, whatever happens to s, once the execution of `foo` is
over, the reference
count at the call site is going to be the same as when `foo` was
called. Why?
Because there is no way you can escape any reference to s outside
of a strongly pure function (other than returning it, but that
case is taken care of at point 1.).
4. If we have two subsequent pure function invocations
foo(args1...) and bar(args2...) where data transitively reachable
from args1 and args2 only overlaps in immutable and const data
(this includes data accessed through __mutable fields of const
and immutable objects), the two invocations may safely swap their
order (of course, this only applies if none of the two functions
takes arguments)
This should be un-affected.
5. A strongly pure function invocation can always exchange order
with an adjacent impure function invocation.
This should be un-affected.
What do you think? Am I missing anything? If you think this could
fly, I could update the DIP and submit it.
Best regards,
RazvanN
More information about the Digitalmars-d
mailing list