August 03, 2020
On Monday, 3 August 2020 at 01:16:37 UTC, Andrei Alexandrescu wrote:
> what the whole deal with OffsetTypeInfo and offTi is. I reckon it's a sort of information on members of a class, but my attempts have been fruitless:

I've never used that and looking at the compiler's source, I just see it outputting null with a comment saying "null for now, fix later"... it might not be implemented. Or if it is, Walter might know better than me as to where it is.
August 03, 2020
> On Monday, 3 August 2020 at 01:16:37 UTC, Andrei Alexandrescu wrote:
> what the whole deal with OffsetTypeInfo

so if I had to guess, this was probably originally intended to support the precise GC and got replaced with RTInfo which uses __traits(getPointerBitmap) now instead.

just speculation.

of course if it were there, that could be potentially cool for runtime reflection stuff. but it should also prolly just be opt-in anyway imo.
August 03, 2020
On Sunday, 2 August 2020 at 23:59:23 UTC, Adam D. Ruppe wrote:
> On Sunday, 2 August 2020 at 22:25:19 UTC, Andrei Alexandrescu wrote:
>> Any ideas on how to do that via introspection? The fields are accessible, but not their default values.
>
> It is ugly but possible right now to pull in the symbol via extern(C).
>
> See line 20 in my latest blog's example:
>
> http://dpldocs.info/this-week-in-d/Blog.Posted_2020_07_27.html#zero-runtime-classes
>
> ldc complains but it is a type mismatch not a fundamental barrier, I just didn't figure out the right thing to silence it yet.
>
>> It seems like __traits(type, getInitializer) might be necessary.
>
> but yes this would be generally nicer anyway imo.

That for that post Adam, I've been trying the same thing lately.
It's needed to fix this: https://issues.dlang.org/show_bug.cgi?id=21097

https://github.com/weka-io/druntime/blob/9e5a36b0fcac242c4d160d3d7d0c85565aebe79f/src/core/internal/lifetime.d#L118

-Johan




August 03, 2020
On 8/3/20 4:04 AM, Johan wrote:
> On Sunday, 2 August 2020 at 23:59:23 UTC, Adam D. Ruppe wrote:
>> On Sunday, 2 August 2020 at 22:25:19 UTC, Andrei Alexandrescu wrote:
>>> Any ideas on how to do that via introspection? The fields are accessible, but not their default values.
>>
>> It is ugly but possible right now to pull in the symbol via extern(C).
>>
>> See line 20 in my latest blog's example:
>>
>> http://dpldocs.info/this-week-in-d/Blog.Posted_2020_07_27.html#zero-runtime-classes 
>>
>>
>> ldc complains but it is a type mismatch not a fundamental barrier, I just didn't figure out the right thing to silence it yet.
>>
>>> It seems like __traits(type, getInitializer) might be necessary.
>>
>> but yes this would be generally nicer anyway imo.
> 
> That for that post Adam, I've been trying the same thing lately.
> It's needed to fix this: https://issues.dlang.org/show_bug.cgi?id=21097
> 
> https://github.com/weka-io/druntime/blob/9e5a36b0fcac242c4d160d3d7d0c85565aebe79f/src/core/internal/lifetime.d#L118 
> 
> 
> -Johan

Would it be effective to iterate through the .tupleof and initialize each in turn?
August 03, 2020
On Monday, 3 August 2020 at 08:04:16 UTC, Johan wrote:
> https://github.com/weka-io/druntime/blob/9e5a36b0fcac242c4d160d3d7d0c85565aebe79f/src/core/internal/lifetime.d#L118

I'm not sure that is a virtual call once it is compiled - it ought to be a candidate for devirtualization and/or inlining since the typeinfo class instance is known at compile time. idk if the implementation actually does that though. The druntime method isn't marked final (it probably could be... the compiler puts out different instances of this object, not different subclasses) but still something like ldc's lto ought to be able to figure it out.

Regardless, yeah, the pragma(mangle) trick can probably help you here too at least as a hacky solution. Let me know if you figure out the incantation to make ldc accept it, or if I come back to it I'll let you know the solution here too. But for dmd it is easy.

August 03, 2020
On Monday, 3 August 2020 at 13:01:55 UTC, Andrei Alexandrescu wrote:
> On 8/3/20 4:04 AM, Johan wrote:
>> On Sunday, 2 August 2020 at 23:59:23 UTC, Adam D. Ruppe wrote:
>>> On Sunday, 2 August 2020 at 22:25:19 UTC, Andrei Alexandrescu wrote:
>>>> Any ideas on how to do that via introspection? The fields are accessible, but not their default values.
>>>
>>> It is ugly but possible right now to pull in the symbol via extern(C).
>>>
>>> See line 20 in my latest blog's example:
>>>
>>> http://dpldocs.info/this-week-in-d/Blog.Posted_2020_07_27.html#zero-runtime-classes
>>>
>>>
>>> ldc complains but it is a type mismatch not a fundamental barrier, I just didn't figure out the right thing to silence it yet.
>>>
>>>> It seems like __traits(type, getInitializer) might be necessary.
>>>
>>> but yes this would be generally nicer anyway imo.
>> 
>> That for that post Adam, I've been trying the same thing lately.
>> It's needed to fix this: https://issues.dlang.org/show_bug.cgi?id=21097
>> 
>> https://github.com/weka-io/druntime/blob/9e5a36b0fcac242c4d160d3d7d0c85565aebe79f/src/core/internal/lifetime.d#L118
>> 
>> 
>> -Johan
>
> Would it be effective to iterate through the .tupleof and initialize each in turn?

Possibly. IIRC, the spec obliges us to initialize the padding in-between address-aligned members aswell, such that a memcmp works to compare structs. If that is true, then we have to initialize the padding aswell and a memcpy would be that much nicer.

If `__traits(type, getInitializer)` would return a symbol, then memcpy is easy and we're done. However, that forces us to emit these init symbols, except for very simple cases like all-zeros initialization (for which LDC does no longer emit an init symbol). It is very benificial for binary size to elide these all-zero initializer symbols. I don't know how much benefit there is for eliding near-zero symbols.
If `__traits(type, getInitializer)` would return a function, then that's a different story...

My current solution [*]: https://github.com/weka-io/druntime/blob/0dab4b0dc5cbccb891351095ff09b0558e3fbe06/src/core/internal/lifetime.d#L92-L140

-Johan

[*] Hits an obscure mangling bug, so doesn't quite work with Weka's codebase yet
August 03, 2020
On Monday, 3 August 2020 at 14:44:38 UTC, Johan wrote:
> If `__traits(type, getInitializer)` would return a function, then that's a different story...

Yes... and then it could skip =void items too. Like

struct A {
  int a = 10;
  ubyte[10000] b = void;
  int c = 20;
}

Could very well just be the two int assigns. Right now it will spit out 10000 zeros in the middle.
August 03, 2020
On Monday, 3 August 2020 at 14:35:27 UTC, Adam D. Ruppe wrote:
>
> Regardless, yeah, the pragma(mangle) trick can probably help you here too at least as a hacky solution. Let me know if you figure out the incantation to make ldc accept it, or if I come back to it I'll let you know the solution here too. But for dmd it is easy.

For structs, `typeof(T.init)` works, but for classes I also have not figured out how to do it. Because a class variable is always a reference (pointer), you basically need something like `typeof(*Klass)`...

-Johan

August 03, 2020
On 8/3/20 10:44 AM, Johan wrote:
> On Monday, 3 August 2020 at 13:01:55 UTC, Andrei Alexandrescu wrote:
>> Would it be effective to iterate through the .tupleof and initialize each in turn?
> 
> Possibly. IIRC, the spec obliges us to initialize the padding in-between address-aligned members aswell, such that a memcmp works to compare structs. If that is true, then we have to initialize the padding aswell and a memcpy would be that much nicer.

To play devil's advocate, the padding bytes should not have been changed by user code in the first place :o).

> If `__traits(type, getInitializer)` would return a symbol, then memcpy is easy and we're done. However, that forces us to emit these init symbols, except for very simple cases like all-zeros initialization (for which LDC does no longer emit an init symbol). It is very benificial for binary size to elide these all-zero initializer symbols. I don't know how much benefit there is for eliding near-zero symbols.
> If `__traits(type, getInitializer)` would return a function, then that's a different story...
> 
> My current solution [*]: https://github.com/weka-io/druntime/blob/0dab4b0dc5cbccb891351095ff09b0558e3fbe06/src/core/internal/lifetime.d#L92-L140 
> 
> 
> -Johan
> 
> [*] Hits an obscure mangling bug, so doesn't quite work with Weka's codebase yet

Cool. Also the https://dlang.org/spec/traits.html#isZeroInit flag may help.

There's also the related trickery TypeInfo uses for the initializer() function:

https://github.com/dlang/druntime/blob/master/src/object.d#L390

Array with null pointer and non-zero length.

There's also offset info for fields available so I'd say there is enough material for a complete solution.

Just throwing everything at the wall...
August 03, 2020
On 8/3/20 10:47 AM, Adam D. Ruppe wrote:
> On Monday, 3 August 2020 at 14:44:38 UTC, Johan wrote:
>> If `__traits(type, getInitializer)` would return a function, then that's a different story...
> 
> Yes... and then it could skip =void items too. Like
> 
> struct A {
>    int a = 10;
>    ubyte[10000] b = void;
>    int c = 20;
> }
> 
> Could very well just be the two int assigns. Right now it will spit out 10000 zeros in the middle.
Oh, yes forgot about that important efficiency matter. Yes it does look like we need a __trait after all.