October 28, 2015

On 10/28/2015 3:31 PM, Andrei Alexandrescu wrote:
> On 10/28/2015 03:53 PM, Walter Bright wrote:
>> That doesn't solve the problem. It would need to be @rc objects from:
>>
>> 1. globals
>> 2. outer scopes
>> 3. fields of aggregates
>> 4. array members
>> 5. any data structure
>
> My assumption is that the compiler gets to "see" during modular analysis 2-5, but not 1. -- Andrei

The objects may be buried in a data structure or be behind opaque function declarations.

_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 28, 2015
On 10/28/2015 07:22 PM, Timon Gehr wrote:
> The question that remains is how the escape analysis should work. (This
> is roughly the reason why Rust introduces lifetime annotations: it makes
> modular a simple form of conservative escape analysis.)

If it becomes clear we need to add an annotation, we will. But with RC we have an easier task than Rust because we start from the conservative side (add an incref for each reference used, named or not) and then we work our way backward. -- Andrei
_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 28, 2015
Le 28 oct. 2015 à 18:39, Timon Gehr <timon.gehr@gmx.ch> a écrit :

> Actually, we do not need #references <= count.
> It's just (#references > 0) -> (count > 0).
> (The converse should also hold, but then #references has to include cyclic references.)

There's still some value in knowing that the total number of references is 1 and not something higher.

Swift has `isUniquelyReferenced` you can use to implement copy-on-write value types in a thread-safe way. I'm not entirely sure why they can guaranty uniqueness for Swift classes; it looks like they can't when it comes to Objective-C classes.


-- 
Michel Fortin
michel.fortin@michelf.ca
https://michelf.ca


_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 29, 2015
On 10/29/2015 01:35 AM, Michel Fortin wrote:
> Le 28 oct. 2015 à 18:39, Timon Gehr <timon.gehr@gmx.ch> a écrit :
>
>> Actually, we do not need #references <= count.
>> It's just (#references > 0) -> (count > 0).
>> (The converse should also hold, but then #references has to include cyclic references.)
>
> There's still some value in knowing that the total number of references is 1 and not something higher.
>
> Swift has `isUniquelyReferenced` you can use to implement copy-on-write value types in a thread-safe way.
> I'm not entirely sure why they can guaranty uniqueness for Swift classes; it looks like they can't when
> it comes to Objective-C classes.
>
>

Good point. However, it seems somewhat costly to support for classes that don't need it.
_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 29, 2015
On 10/29/2015 12:26 AM, Andrei Alexandrescu wrote:
> On 10/28/2015 07:22 PM, Timon Gehr wrote:
>> The question that remains is how the escape analysis should work. (This
>> is roughly the reason why Rust introduces lifetime annotations: it makes
>> modular a simple form of conservative escape analysis.)
>
> If it becomes clear we need to add an annotation, we will. But with RC
> we have an easier task than Rust because we start from the conservative
> side (add an incref for each reference used, named or not) and then we
> work our way backward. -- Andrei

The post this is a reply to seems to have been lost. I'm sending it again below.

On 10/28/2015 11:42 PM, Andrei Alexandrescu wrote:
>
> Fantastic. That's why you're paid the big bucks! :o)

:)

Michel's post touches very related points.
scope arguments would be implicitly non-consuming, but it still makes sense to have non-consuming arguments that may still be escaped. The point here is that a method with a non-consuming argument can elide even the initial and final opInc/opDec in the described transformation, because the caller guarantees to keep alive the reference until after the method returns. (OTOH, there are also cases where consumption is exactly what you want, e.g. when constructing objects that contain rc references.)

The question that remains is how the escape analysis should work. (This is roughly the reason why Rust introduces lifetime annotations: it makes modular a simple form of conservative escape analysis.)
_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 29, 2015
On 10/28/2015 08:35 PM, Michel Fortin wrote:
> Le 28 oct. 2015 à 18:39, Timon Gehr <timon.gehr@gmx.ch> a écrit :
>
>> Actually, we do not need #references <= count.
>> It's just (#references > 0) -> (count > 0).
>> (The converse should also hold, but then #references has to include cyclic references.)
>
> There's still some value in knowing that the total number of references is 1 and not something higher.

Particularly important with COW. -- Andrei
_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 29, 2015
Le 28 oct. 2015 à 20:47, Timon Gehr <timon.gehr@gmx.ch> a écrit :

> On 10/29/2015 01:35 AM, Michel Fortin wrote:
>> Le 28 oct. 2015 à 18:39, Timon Gehr <timon.gehr@gmx.ch> a écrit :
>> 
>>> Actually, we do not need #references <= count.
>>> It's just (#references > 0) -> (count > 0).
>>> (The converse should also hold, but then #references has to include cyclic references.)
>> 
>> There's still some value in knowing that the total number of references is 1 and not something higher.
>> 
>> Swift has `isUniquelyReferenced` you can use to implement copy-on-write value types in a thread-safe way. I'm not entirely sure why they can guaranty uniqueness for Swift classes; it looks like they can't when it comes to Objective-C classes.
> 
> Good point. However, it seems somewhat costly to support for classes that don't need it.

I think I understand how Swift's `isUniquelyReferenced` works. It's not costly. It's also quite clever. I'll rewrite the function signature to its D equivalent for this discussion:

	bool isUniquelyReferenced(ref Object o);

This function simply returns true if the counter for "o" is 1. Note that the parameter is 'ref' to avoid the counter being incremented when passing the object to the function. It is also imperative that you do NOT make it 'const ref' if you want the function to work in the presence of the optimizer. By telling the compiler in the function signature that it might mutate the variable, it prevents opInc/opDec elision from occurring in the caller's context. I'll try to illustrate.

Say you have this code:

	auto o{+1} = new O(){-1};
	isUniquelyReferenced(o);
	o{-1}; // end of scope

Here you can elide the {-1} and {+1} on the first line and the reference count is reliably 1, falling to zero at the end of the scope. `isUniquelyReferenced` returns true.

	auto o = new O();
	isUniquelyReferenced(o);
	o{-1}; // end of scope

Now let's add a second reference:

	auto o = new O();
	auto p{+1} = o;
	isUniquelyReferenced(o);
	p{-1}; // end of scope
	o{-1};

Here it might seem that you could elide the p{+1} and p{-1} because it's the same value as o, and o outlives it. But no: the compiler does not know knows whether o's value will outlive p because `isUniquelyReferenced` takes a mutable reference to o. So you can't elide the opInc/opDec for p, the reference count reaches 2, and `isUniquelyReferenced` returns false.

If you removed the call to `isUniquelyReferenced`, then it would optimize like this:

	auto o = new O();
	auto p = o;
	o{-1}; // end of scope

Ingenious.


-- 
Michel Fortin
michel.fortin@michelf.ca
https://michelf.ca


_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 29, 2015
On 10/29/2015 03:33 PM, Michel Fortin wrote:
> Le 28 oct. 2015 à 20:47, Timon Gehr <timon.gehr@gmx.ch> a écrit :
>
>> On 10/29/2015 01:35 AM, Michel Fortin wrote:
>>> Le 28 oct. 2015 à 18:39, Timon Gehr <timon.gehr@gmx.ch> a écrit :
>>>
>>>> Actually, we do not need #references <= count.
>>>> It's just (#references > 0) -> (count > 0).
>>>> (The converse should also hold, but then #references has to include cyclic references.)
>>>
>>> There's still some value in knowing that the total number of references is 1 and not something higher.
>>>
>>> Swift has `isUniquelyReferenced` you can use to implement copy-on-write value types in a thread-safe way.
>>> I'm not entirely sure why they can guaranty uniqueness for Swift classes; it looks like they can't when
>>> it comes to Objective-C classes.
>>
>> Good point. However, it seems somewhat costly to support for classes that don't need it.
>
> I think I understand how Swift's `isUniquelyReferenced` works. It's not costly. It's also quite clever. I'll rewrite the function signature to its D equivalent for this discussion:
>
> 	bool isUniquelyReferenced(ref Object o);
>
> This function simply returns true if the counter for "o" is 1.

By somewhat costly, I mean that it prevents transformations that do not satisfy (#references=1) <-> (count=1).


> Note that the parameter is 'ref' to avoid the counter being incremented when passing the object to the function. It is also imperative that you do NOT make it 'const ref' if you want the function to work in the presence of the optimizer. By telling the compiler in the function signature that it might mutate the variable, it prevents opInc/opDec elision from occurring in the caller's context. I'll try to illustrate.
>...
>
> Ingenious.
>
>

It's what I'd call a hack though. :o)
It does not work well with inlining.
_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 29, 2015
On 10/29/2015 10:33 AM, Michel Fortin wrote:
[snip]

Well yah as Timon said it's kind of an odd thing - a semi-intrinsic function relying on no inlining.

Anyhow, let me add to our fledgling requirements list that we do need a function like isUniquelyReferenced so people can do copy on write.

Andrei
_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 29, 2015
Le 29 oct. 2015 à 12:14, Timon Gehr <timon.gehr@gmx.ch> a écrit :

> On 10/29/2015 03:33 PM, Michel Fortin wrote:
>> I think I understand how Swift's `isUniquelyReferenced` works. It's not costly. It's also quite clever. I'll rewrite the function signature to its D equivalent for this discussion:
>> 
>> 	bool isUniquelyReferenced(ref Object o);
>> 
>> This function simply returns true if the counter for "o" is 1.
> 
> By somewhat costly, I mean that it prevents transformations that do not satisfy (#references=1) <-> (count=1).

True, however:

1. It has the effect of preventing an elision only where you actually call the function, which is the same cost as any function taking a RC parameter by ref.

2. Any time `isUniquelyReferenced` prevents an opInc/opDec elision, it is guarantied to return false. If you made it an intrinsic you could take advantage of that by replacing the call with a false constant whenever it would get in the way of an elision.

3. Even without the intrinsic, if you use it to implement copy-on-write, any time it prevents an elision is a time you'll end up making a copy, and the copy going to be more costly regardless.


-- 
Michel Fortin
michel.fortin@michelf.ca
https://michelf.ca


_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

1 2 3 4
Next ›   Last »