September 21, 2021
On Monday, 20 September 2021 at 18:26:59 UTC, Steven Schveighoffer wrote:
> Without any context

Some context in my blog now:

http://dpldocs.info/this-week-in-d/Blog.Posted_2021_09_20.html#my-investigation
September 22, 2021

On Monday, 20 September 2021 at 18:49:12 UTC, Steven Schveighoffer wrote:

>

This to me seems like "leaving a pointer to it on the stack". I'm not sure how else I would do that specifically? Plus, this option is the only "free" one -- the others all require much more complication. Adding a pointer to the stack is free. It's just, I don't know how to tell the compiler to do that besides declaring it.

If you use the pointer after the call, that's an easy way to ensure that the pointer is kept around long enough.

September 22, 2021

On 9/22/21 8:12 AM, Kagamin wrote:

>

On Monday, 20 September 2021 at 18:49:12 UTC, Steven Schveighoffer wrote:

>

This to me seems like "leaving a pointer to it on the stack". I'm not sure how else I would do that specifically? Plus, this option is the only "free" one -- the others all require much more complication. Adding a pointer to the stack is free. It's just, I don't know how to tell the compiler to do that besides declaring it.

If you use the pointer after the call, that's an easy way to ensure that the pointer is kept around long enough.

The point is, you may only use it via functions/mechanisms that are not visible to the GC (like C libraries). In which case you have to pin it somehow.

Having to "fake" usage is annoying, but I think we should at least provide foolproof guidance on how to do this.

-Steve

September 22, 2021

On 9/22/21 8:12 AM, Kagamin wrote:

>

On Monday, 20 September 2021 at 18:49:12 UTC, Steven Schveighoffer wrote:

>

This to me seems like "leaving a pointer to it on the stack". I'm not sure how else I would do that specifically? Plus, this option is the only "free" one -- the others all require much more complication. Adding a pointer to the stack is free. It's just, I don't know how to tell the compiler to do that besides declaring it.

If you use the pointer after the call, that's an easy way to ensure that the pointer is kept around long enough.

And by the way I tried naive usage, and the compiler saw right through that:

auto c = new C;
scope(exit) auto fake = c; // still collected early

-Steve

September 22, 2021

On Wednesday, 22 September 2021 at 12:31:48 UTC, Steven Schveighoffer wrote:

>

On 9/22/21 8:12 AM, Kagamin wrote:

>

On Monday, 20 September 2021 at 18:49:12 UTC, Steven Schveighoffer wrote:

>

This to me seems like "leaving a pointer to it on the stack". I'm not sure how else I would do that specifically? Plus, this option is the only "free" one -- the others all require much more complication. Adding a pointer to the stack is free. It's just, I don't know how to tell the compiler to do that besides declaring it.

If you use the pointer after the call, that's an easy way to ensure that the pointer is kept around long enough.

And by the way I tried naive usage, and the compiler saw right through that:

auto c = new C;
scope(exit) auto fake = c; // still collected early

I think anything that is (close to) zero-overhead is what the optimizer understands and is therefore not going to get the behavior that you want, besides an intrinsic to tell the optimizer to keep that pointer value alive in some storage that is scanned by GC (reachable memory or registers).

In the absence of such intrinsic [*], what you can do is pass the value to something about which we explicitly tell the optimizer that it does not understand it. Cryptic? ;)

https://d.godbolt.org/z/M3zbzK4sq

   import ldc.llvmasm;
   __asm("", "r", c);

Probably this is also expressible in the new inline assembly that both GDC and LDC support.

-Johan

[*] https://lists.llvm.org/pipermail/llvm-dev/2016-July/102322.html Where it popped up in debuggability considerations.

September 22, 2021
On 9/22/21 11:16 AM, Johan wrote:

> besides an intrinsic to tell the optimizer to keep that pointer
> value alive in some storage that is scanned by GC (reachable memory or
> registers).

Nobody seems to see the violation of "lifetime being the length of the scope" being a problem here. (You mentioned it elsewhere in this thread.) I think this is because the same issue is present in other languages.

Shouldn't preserving the contents of registers be the responsibility of the compiler or the GC? And perhaps the compiler should skip that optimization if the contents cannot be preserved?

Ali

September 22, 2021
On Wednesday, 22 September 2021 at 18:30:41 UTC, Ali Çehreli wrote:
>
> Shouldn't preserving the contents of registers be the responsibility of the compiler or the GC? And perhaps the compiler should skip that optimization if the contents cannot be preserved?
>
> Ali

Not according to most ABIs. Parameters are usually not preserved on stack. Should it be forced on stack because of FFI? I personally don't think so.

I think you are attacking this problem from the wrong side. It is not a problem of the optimizer or code generation. It's not the problem of the ABI. It's a life time issue regardless of the type of GC you use. If a resource is moved (both temporary and permanent) to any foreign system, you must have a way of describing that.
September 22, 2021
On Wednesday, 22 September 2021 at 18:30:41 UTC, Ali Çehreli wrote:
> Shouldn't preserving the contents of registers be the responsibility of the compiler or the GC?

The compiler thinks the contents don't need to be preserved at all.

One thing we might do is if passing a pointer to an extern(C) function, the compiler assumes it shouldn't stomp the memory until end of scope.
September 22, 2021

On 9/22/21 3:10 PM, Adam D Ruppe wrote:

>

On Wednesday, 22 September 2021 at 18:30:41 UTC, Ali Çehreli wrote:

>

Shouldn't preserving the contents of registers be the responsibility of the compiler or the GC?

The compiler thinks the contents don't need to be preserved at all.

One thing we might do is if passing a pointer to an extern(C) function, the compiler assumes it shouldn't stomp the memory until end of scope.

What if you are calling D functions that call extern(C) functions?

I don't think this is the answer either.

-Steve

September 22, 2021
On Wednesday, 22 September 2021 at 19:14:43 UTC, Steven Schveighoffer wrote:
> What if you are calling D functions that call extern(C) functions?

Then it will be an argument to that other D function which makes it a local variable there and the same rule can apply.

If the C function stores something beyond the immediate function, you are already supposed to malloc it or addRoot etc, so I don't think the depth of the call stack really makes a difference.