4 ms·
As you know, in do_thing you have taken a mutable pointer to l and placed it in a location where someone else could access it. Thefore, before the call to foo1
by Negitivefrags 5y ago
As you know, in do_thing you have taken a mutable pointer to l and placed it in a location where someone else could access it.
Thefore, before the call to foo1, the compiler simply creates a copy of l, and then passes an immutable pointer to that to foo1. Effectively falling back to how the old ABI worked.
The code generated for foo1 does depend on the code that calls foo1. That is what an ABI is. An ABI is a specification of the contract between the caller and the callee.
The proposed new ABI says "If you are passing a struct by value, then you, the caller, will give me a pointer that you guarantee can't be modified until I return. In turn, I guarantee that I will not modify the pointer you give me."
- mort96 5y agoI think I understand what you're saying now, and where the confusion is. My understanding of the ABI was: "The callee will always receive a pointer to the caller's copy. If the callee can't guarantee that nothing modifies the caller's copy, the callee makes a copy." Your understanding is subtly different, because the caller guarantees that nothing else has a pointer to the parameter (and the caller guarantees that by making a copy when that's the only option). To be honest, I think the ABI according to my understanding is better. It does reduce the amount of cases a copy can be avoided, but it means that the worst-case is that one copy is made (by the callee). With your version, you would have a bunch of situations where the caller has to make a copy (because a pointer has escaped) and the callee has to make a copy (because it modifies the object). With my version, the worst-case is that a copy is made once (by the callee), but the worst-case would be hit more often. I think my understanding is closer to the intent of the article, due to this sentence: "In the event that a copy is needed, it will happen only once, in the callee, rather than needing to be repeated by every caller." In your version, the copy is sometimes made in the caller and sometimes in the callee.
- Negitivefrags 5y agoLook at the very next sentence. > The callee also has more flexibility, and can copy only those portions of the structure that are actually modified. It's clear that the author understands that the callee needs to copy any value it wants to modify. But also, your understanding doesn't actually work, due to the issue you mentioned. So I think it's pretty unreasonable to assume that is what the author meant.
- mort96 5y agoWait what issue are you referring to? My version absolutely works, it just falls back to making one copy a lot. In my version the callee can absolutely make a copy of only the modified fields if the function A) modifies some fields but not others and B) doesn't do anything which demands a full copy. Anyways, discussion on the intent of the article isn't super productive, I wrote a reply to https://news.ycombinator.com/item?id=27091726 https://news.ycombinator.com/item?id=27091726 which asks the author what their intention was.
- Negitivefrags 5y agoSorry, you are correct. I was thinking about the post at the top of this chain that wasn't actually made by you.
- a1369209993 5y ago> My version absolutely works, Consider: void other_thread(struct large* l) { struct large new_l = { ... }; *l = new_l; } void do_other_thing() { struct large l = { ... }; thread_t t = start_thread(other_thread,&l); foo1(l); wait_for_thread(t); } Not only can `foo1` never avoid making a copy (because it can't assume it's unknown caller is not this perverse), it can't even make a copy safely unless its caller allocates a new `struct large` for it to copy from. (And the caller does not, in general, know that `start_thread` (or `process_thingy_maybe_concurrently^W^W`) starts a thread with the aliased `&l`, so it would have to make such copies on any substantially escaping alias just to be sure, at which point you're back to the original proposal.) The pass-by-non-mutatably-aliased-reference ABI seems terrible IMO, but it at least allows the callee to decide whether to copy using only information that's actually present in the callee.