September 23, 2021

On Monday, 20 September 2021 at 18:26:59 UTC, Steven Schveighoffer wrote:

>

Option 4:
Option 1 or 2, depending on entropy.

This ^

September 23, 2021

On 9/23/21 6:54 AM, Johan wrote:

>

For the simple Pin version above, LDC generates the same machine code with/without Pin (as expected):

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

So that's not showing the issue (without the -version=PIN)

I couldn't get it to show on certain platforms, including ldc 64-bit. On 32-bit it does fail, and the PIN fixes it.

HOWEVER, I have implemented a suggestion by Adam that perhaps the reason the first call to GC.collect doesn't cause a collection to occur is because the leftover stack might contain some reference, and it's not sufficiently clobbered. So adding:

void foo()
{
   int[1000] x;
   writeln(x[1]);
}

And calling that function before calling GC.collect Seems to do the trick for 64 bit. Adding a new wrinkle here is that now BOTH versions collect early.

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

And even dmd -inline -O is smart enough to see through this.

So I added the opaque function call, and even that wasn't enough (it didn't use any variables)

So I added passing the t through the opaque function, and this has fooled dmd, but not ldc (which I'm guessing is doing optimization on the mangled name, and so can see right through my opaque trick). Possibly, we could create a truly opaque library function. I also tried just putting an empty asm block inside.

But I can't be certain if it's working or not, the results are inconsistently showing both outputs.

I think we will need a real compiler intrinsic at this point.

-Steve

September 23, 2021

On 9/23/21 8:47 AM, Steven Schveighoffer wrote:

>

So that's not showing the issue (without the -version=PIN)

Nevermind, the important thing to read there is that it's not pushing it onto the stack. Whether the collection happens early or not is dependent on whether some other reference exists somewhere else (either on the stack or somewhere else).

So the problem then is intermittent, depending on whether some other stack reference is seen.

Frustrating...

-Steve

September 23, 2021

On 9/22/21 5:06 PM, Steven Schveighoffer wrote:

>

I made a package for something like this: https://code.dlang.org/packages/keepalive

Maybe it might find some use.

I deregistered it as it doesn't work to solve the problem (it might superficially solve it, but not definitively).

-Steve

September 23, 2021

On Thursday, 23 September 2021 at 12:47:25 UTC, Steven Schveighoffer wrote:

>

I think we will need a real compiler intrinsic at this point.

For LDC (and I expect GDC too), the asm trick works.

-Johan

September 23, 2021

On 9/23/21 1:45 PM, Johan wrote:

>

On Thursday, 23 September 2021 at 12:47:25 UTC, Steven Schveighoffer wrote:

>

I think we will need a real compiler intrinsic at this point.

For LDC (and I expect GDC too), the asm trick works.

oooh, really? That's cool. Maybe I'll update the library and re-register.

Looking at the disassembly, I do see the difference. This is it pushing to the stack, right?

 mov     qword ptr [rsp], rax

-Steve

September 23, 2021

On Thursday, 23 September 2021 at 18:41:55 UTC, Steven Schveighoffer wrote:

>

On 9/23/21 1:45 PM, Johan wrote:

>

On Thursday, 23 September 2021 at 12:47:25 UTC, Steven Schveighoffer wrote:

>

I think we will need a real compiler intrinsic at this point.

For LDC (and I expect GDC too), the asm trick works.

oooh, really? That's cool. Maybe I'll update the library and re-register.

Looking at the disassembly, I do see the difference. This is it pushing to the stack, right?

 mov     qword ptr [rsp], rax

-Steve

RSP is the stack pointer and [RSP] refers to its value, so yes.

I will have a look at the LLVM GC intrinsics when I get round to it.

September 23, 2021

On 9/23/21 2:41 PM, Steven Schveighoffer wrote:

>

On 9/23/21 1:45 PM, Johan wrote:

>

On Thursday, 23 September 2021 at 12:47:25 UTC, Steven Schveighoffer wrote:

>

I think we will need a real compiler intrinsic at this point.

For LDC (and I expect GDC too), the asm trick works.

oooh, really? That's cool. Maybe I'll update the library and re-register.

Looking at the disassembly, I do see the difference. This is it pushing to the stack, right?

  mov     qword ptr [rsp], rax

Hm... it cancels all optimizations. No inlining either, or removal of the empty function. So the penalty is you are going to call the dtor (with an actual call instruction).

I guess that's better than nothing.

-Steve

September 23, 2021

On Thursday, 23 September 2021 at 18:41:55 UTC, Steven Schveighoffer wrote:

>

On 9/23/21 1:45 PM, Johan wrote:

>

On Thursday, 23 September 2021 at 12:47:25 UTC, Steven Schveighoffer wrote:

>

I think we will need a real compiler intrinsic at this point.

For LDC (and I expect GDC too), the asm trick works.

oooh, really? That's cool. Maybe I'll update the library and re-register.

Looking at the disassembly, I do see the difference. This is it pushing to the stack, right?

 mov     qword ptr [rsp], rax

-Steve

It should, that is also what the keep alive from C# and Go that I post earlier do.

You are supposed to use keepalive this way:

auto c = new C;
// ... lots of ongoing activities ...
keepAlive(c); // c will survive until keepAlive returns.

If you look into their source code, they then trick to trick the optimizer that keepAlive is relevant and shouldn't be taken away, thus forcing the GC to ensure that the reference isn't collected until function returns.

https://cs.opensource.google/go/go/+/refs/tags/go1.17.1:src/runtime/mfinal.go;l=473

I think the mistake was trying to force c to exist on the stack, but without being used.

-- Paulo

September 23, 2021
On Thu, Sep 23, 2021 at 03:22:26PM -0400, Steven Schveighoffer via Digitalmars-d wrote:
> On 9/23/21 2:41 PM, Steven Schveighoffer wrote:
> > On 9/23/21 1:45 PM, Johan wrote:
> > > On Thursday, 23 September 2021 at 12:47:25 UTC, Steven Schveighoffer wrote:
> > > > 
> > > > I think we will need a real compiler intrinsic at this point.
> > > 
> > > For LDC (and I expect GDC too), the asm trick works.
> > 
> > oooh, really? That's cool. Maybe I'll update the library and re-register.
> > 
> > Looking at the disassembly, I do see the difference. This is it pushing to the stack, right?
> > 
> > ```asm
> >   mov     qword ptr [rsp], rax
> > ```
> 
> Hm... it cancels all optimizations. No inlining either, or removal of the empty function. So the penalty is you are going to call the dtor (with an actual call instruction).
> 
> I guess that's better than nothing.
[...]

All of this long discussion begs the question: why not just use
GC.addRoot() and call it a day?


T

-- 
He who laughs last thinks slowest.