www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Object.factory() and exe file size bloat

reply Walter Bright <newshound2 digitalmars.com> writes:
This function:



enables a program to instantiate any class defined in the program. To make it 
work, though, every class in the program has to have a TypeInfo generated for 
it. This leads to bloat:

   https://issues.dlang.org/show_bug.cgi?id=14758

and sometimes the bloat can be overwhelming.

The solution seems straightforward - only have Object.factory be able to 
instantiate classes marked as 'export'. This only makes sense anyway.

What do you think?
Aug 20 2015
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 21-Aug-2015 08:06, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the program. To
 make it work, though, every class in the program has to have a TypeInfo
 generated for it. This leads to bloat:

    https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory be able to
 instantiate classes marked as 'export'. This only makes sense anyway.

 What do you think?
+1000 Though I'd kill the whole object factory if I had a chance. It looks a lot like Java-woannabe feature that may be better done with UDA's and meta-programming (like e.g. run--time type info can be based on compile-time one). -- Dmitry Olshansky
Aug 20 2015
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the 
 program. To make it work, though, every class in the program 
 has to have a TypeInfo generated for it. This leads to bloat:

   https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory 
 be able to instantiate classes marked as 'export'. This only 
 makes sense anyway.

 What do you think?
Wait ? Why only classes marked export ? I don't follow the reasoning here.
Aug 20 2015
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Fri, Aug 21, 2015 at 05:15:00AM +0000, deadalnix via Digitalmars-d wrote:
 On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
This function:



enables a program to instantiate any class defined in the program. To
make it work, though, every class in the program has to have a
TypeInfo generated for it. This leads to bloat:

  https://issues.dlang.org/show_bug.cgi?id=14758

and sometimes the bloat can be overwhelming.

The solution seems straightforward - only have Object.factory be able
to instantiate classes marked as 'export'. This only makes sense
anyway.

What do you think?
Wait ? Why only classes marked export ? I don't follow the reasoning here.
Because if your code imports the module that defines the class, you already know the class name (either by design, or by compile-time introspection) so you don't need to use the object factory. It's only when you want to dynamically load new classes at runtime that you didn't know about at compile-time, that you need to use the object factory -- and that's also when you'd mark classes as 'export'. Makes sense to me. T -- Windows: the ultimate triumph of marketing over technology. -- Adrian von Bidder
Aug 20 2015
parent Johannes Pfau <nospam example.com> writes:
Am Thu, 20 Aug 2015 22:21:30 -0700
schrieb "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com>:

 On Fri, Aug 21, 2015 at 05:15:00AM +0000, deadalnix via Digitalmars-d
 wrote:
 On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
This function:



enables a program to instantiate any class defined in the program.
To make it work, though, every class in the program has to have a
TypeInfo generated for it. This leads to bloat:

  https://issues.dlang.org/show_bug.cgi?id=14758

and sometimes the bloat can be overwhelming.

The solution seems straightforward - only have Object.factory be
able to instantiate classes marked as 'export'. This only makes
sense anyway.

What do you think?
Wait ? Why only classes marked export ? I don't follow the reasoning here.
Because if your code imports the module that defines the class, you already know the class name (either by design, or by compile-time introspection) so you don't need to use the object factory. It's only when you want to dynamically load new classes at runtime that you didn't know about at compile-time, that you need to use the object factory -- and that's also when you'd mark classes as 'export'. Makes sense to me. T
As Benjamin explained export works on library level, not on module level. You export from a library (DLL/.so) not from a module, so the analogy with D's 'import' is flawed.
Aug 21 2015
prev sibling next sibling parent reply "BBasile" <bb.temp gmx.com> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the 
 program. To make it work, though, every class in the program 
 has to have a TypeInfo generated for it:

 [...]

 What do you think?
This is a good idea. Some other langs use a similar system with a registration. Eg instances can only be streamed if type is registered. Other alternatives would be a pragma or an attribute to disable TypeInfo generation. NoTI.
Aug 20 2015
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/20/2015 10:24 PM, BBasile wrote:
 Other alternatives would be a pragma or an attribute to disable TypeInfo
 generation.
Interestingly, my idea would not disable TypeInfo generation. Instead, the TypeInfo would be generated into a COMDAT section. Then, only if it is referenced is it linked in. The ModuleInfo, as it currently is implemented, contains a reference to every class TypeInfo, thus pulling them all in.
Aug 20 2015
parent reply "Mike" <none none.com> writes:
On Friday, 21 August 2015 at 05:35:21 UTC, Walter Bright wrote:
 On 8/20/2015 10:24 PM, BBasile wrote:
 Other alternatives would be a pragma or an attribute to 
 disable TypeInfo
 generation.
Interestingly, my idea would not disable TypeInfo generation. Instead, the TypeInfo would be generated into a COMDAT section. Then, only if it is referenced is it linked in.
Disabling TypeInfo forces one to compromise on slicing, postblit, and potentially others useful features, so finding a way to keep TypeInfo, yet remove the dead code is much less of a blunt instrument, and very much preferred.
 The ModuleInfo, as it currently is implemented, contains a 
 reference to every class TypeInfo, thus pulling them all in.
Ideally it would be nice to only pull in those ModuleInfo instances that are actually needed in the program, and by association, only pull in those TypeInfo instances needed by the ModuleInfo. If no ModuleInfo is used, and the associated TypeInfo is also not used, then neither is pulled in. Mike
Aug 20 2015
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/20/2015 11:00 PM, Mike wrote:
 Ideally it would be nice to only pull in those ModuleInfo instances that are
 actually needed in the program, and by association, only pull in those TypeInfo
 instances needed by the ModuleInfo.  If no ModuleInfo is used, and the
 associated TypeInfo is also not used, then neither is pulled in.
I do plan to do a review of ModuleInfo with this in mind, but not immediately.
Aug 20 2015
parent reply Johannes Pfau <nospam example.com> writes:
Am Thu, 20 Aug 2015 23:16:10 -0700
schrieb Walter Bright <newshound2 digitalmars.com>:

 On 8/20/2015 11:00 PM, Mike wrote:
 Ideally it would be nice to only pull in those ModuleInfo instances
 that are actually needed in the program, and by association, only
 pull in those TypeInfo instances needed by the ModuleInfo.  If no
 ModuleInfo is used, and the associated TypeInfo is also not used,
 then neither is pulled in.
I do plan to do a review of ModuleInfo with this in mind, but not immediately.
Right now we use ModuleInfo to iterate all linked modules*. Keeping modules but removing the ModuleInfo seems irreconcilable with that use case? Of course completely removing a module could work. *: foreach(mod; ModuleInfo) is used in * druntime to run unittests for all modules * gdc druntime to find all modules with TLS variables for emulated TLS support * IIRC also somehow used in dynamic shared library loading/unloading?
Aug 21 2015
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/21/15 6:59 AM, Johannes Pfau wrote:
 Am Thu, 20 Aug 2015 23:16:10 -0700
 schrieb Walter Bright <newshound2 digitalmars.com>:

 On 8/20/2015 11:00 PM, Mike wrote:
 Ideally it would be nice to only pull in those ModuleInfo instances
 that are actually needed in the program, and by association, only
 pull in those TypeInfo instances needed by the ModuleInfo.  If no
 ModuleInfo is used, and the associated TypeInfo is also not used,
 then neither is pulled in.
I do plan to do a review of ModuleInfo with this in mind, but not immediately.
Right now we use ModuleInfo to iterate all linked modules*. Keeping modules but removing the ModuleInfo seems irreconcilable with that use case? Of course completely removing a module could work. *: foreach(mod; ModuleInfo) is used in * druntime to run unittests for all modules * gdc druntime to find all modules with TLS variables for emulated TLS support * IIRC also somehow used in dynamic shared library loading/unloading?
It's used to call static ctor/dtors as well. I think for modules that have none of these features, you could omit the ModuleInfo. -Steve
Aug 21 2015
prev sibling parent reply "Kagamin" <spam here.lot> writes:
On Friday, 21 August 2015 at 06:00:44 UTC, Mike wrote:
 Disabling TypeInfo forces one to compromise on slicing, postblit
Why slicing and postblit would need typeinfo?
Aug 21 2015
next sibling parent reply "Mike" <none none.com> writes:
On Friday, 21 August 2015 at 08:11:37 UTC, Kagamin wrote:
 On Friday, 21 August 2015 at 06:00:44 UTC, Mike wrote:
 Disabling TypeInfo forces one to compromise on slicing, 
 postblit
Why slicing and postblit would need typeinfo?
See below for the source code. Some obvious, some not. * dynamic cast - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-83bcb64558f947e39f87d7435709dfe7R364 * array literal - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-bed7d2226948b1e098749985d7a60633R2353 * postblit - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR918 * destructor - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1 63d02e24318bbR1039, https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-867588d7078efd0364c256152fb5a2e7R2053 * new - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R5091 * AAs - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R10710 * slicing - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R11857 etc... Disabling TypeInfo requires quite a compromise on D's features. I want TypeInfo, I just don't want dead code. Mike
Aug 21 2015
next sibling parent Johannes Pfau <nospam example.com> writes:
Am Fri, 21 Aug 2015 11:03:00 +0000
schrieb "Mike" <none none.com>:

 On Friday, 21 August 2015 at 08:11:37 UTC, Kagamin wrote:
 On Friday, 21 August 2015 at 06:00:44 UTC, Mike wrote:
 Disabling TypeInfo forces one to compromise on slicing, 
 postblit
Why slicing and postblit would need typeinfo?
See below for the source code. Some obvious, some not. * dynamic cast - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-83bcb64558f947e39f87d7435709dfe7R364 * array literal - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-bed7d2226948b1e098749985d7a60633R2353 * postblit - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR918 * destructor - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR1039, https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-867588d7078efd0364c256152fb5a2e7R2053 * new - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R5091 * AAs - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R10710 * slicing - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R11857 etc... Disabling TypeInfo requires quite a compromise on D's features. I want TypeInfo, I just don't want dead code. Mike
It's been some time since I looked at this so I don't remember exactly how severe these limitations are. However, it should be noted that not all 'array literals', ... need TypeInfo, only a subset of them does. Some are fixable others (dynamic downcast) probably not.
Aug 21 2015
prev sibling next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/21/15 7:03 AM, Mike wrote:
 On Friday, 21 August 2015 at 08:11:37 UTC, Kagamin wrote:
 On Friday, 21 August 2015 at 06:00:44 UTC, Mike wrote:
 Disabling TypeInfo forces one to compromise on slicing, postblit
Why slicing and postblit would need typeinfo?
See below for the source code. Some obvious, some not. * dynamic cast - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-83bcb64558f947e39f87d7435709dfe7R364
You need some static data to hold the vtable. I think typeinfo is fine to have for this, but I don't think it's actually necessary.
 * array literal -
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-bed7d2226948b1e098749985d7a60633R2353

 * postblit -
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR918

 * destructor -
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR1039,
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-867588d7078efd0364c256152fb5a2e7R2053

 * new -
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R5091

 * AAs -
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R10710

 * slicing -
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R11857
These are all runtime limitations rooted in legacy that could be lifted. If druntime was just hooks that the compiler called with the type as a template parameter, we could fix all this. -Steve
Aug 21 2015
prev sibling next sibling parent reply Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 21 August 2015 at 13:03, Mike via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Friday, 21 August 2015 at 08:11:37 UTC, Kagamin wrote:

 On Friday, 21 August 2015 at 06:00:44 UTC, Mike wrote:

 Disabling TypeInfo forces one to compromise on slicing, postblit
Why slicing and postblit would need typeinfo?
See below for the source code. Some obvious, some not. * dynamic cast - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-83bcb64558f947e39f87d7435709dfe7R364 * array literal - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-bed7d2226948b1e098749985d7a60633R2353 * postblit - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR918 * destructor - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR1039, https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-867588d7078efd0364c256152fb5a2e7R2053 * new - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R5091 * AAs - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R10710 * slicing - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R11857 etc... Disabling TypeInfo requires quite a compromise on D's features. I want TypeInfo, I just don't want dead code.
Where removing RTTI disables D feature's in a compromising way, I'd start by questioning the why. Eg: Why does array literals need RTTI? Looking at _d_arrayliteralTX implementation, it only does the following with the given TypeInfo provided: - Get the array element size (this is known at compile time) - Get the array element type flags (calculated during the codegen stage, but otherwise known at compile time) - Test if the TypeInfo is derived from TypeInfo_Shared (can be done at - you guessed it - compile time by peeking through the baseClass linked list for a given TypeInfo type we are passing). So we have this function that accepts a TypeInfo, but doesn't really *need* to at all. void* _d_arrayliteralTX(size_t length, size_t sizeelem, uint flags, bool isshared); Just putting it out there.... Iain.
Aug 21 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/21/15 7:22 AM, Iain Buclaw via Digitalmars-d wrote:
 Where removing RTTI disables D feature's in a compromising way, I'd
 start by questioning the why.

 Eg:  Why does array literals need RTTI?  Looking at _d_arrayliteralTX
 implementation, it only does the following with the given TypeInfo provided:

 - Get the array element size (this is known at compile time)
 - Get the array element type flags (calculated during the codegen stage,
 but otherwise known at compile time)
 - Test if the TypeInfo is derived from TypeInfo_Shared (can be done at -
 you guessed it - compile time by peeking through the baseClass linked
 list for a given TypeInfo type we are passing).

 So we have this function that accepts a TypeInfo, but doesn't really
 *need* to at all.

 void* _d_arrayliteralTX(size_t length, size_t sizeelem, uint flags, bool
 isshared);

 Just putting it out there....
I strongly suggest we *don't* go this route. This means that any changes to what is required for the runtime to properly construct an array requires a compiler change. A MUCH better solution: T[] _d_arrayliteral(T)(size_t length) Also, isn't the typeinfo now stored by the GC so it can call the dtor? Perhaps that is done in the filling of the array literal, but I would be surprised as this is a GC feature. -Steve
Aug 21 2015
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 21 August 2015 at 11:34:58 UTC, Steven Schveighoffer 
wrote:
 A MUCH better solution:

 T[] _d_arrayliteral(T)(size_t length)
It needs to be trivial wrapper which forwards to proposed
 void* _d_arrayliteralTX(size_t length, size_t sizeelem, uint 
 flags, bool
 isshared);
Otherwise you get another binary bloat issue.
Aug 21 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/21/15 7:39 AM, Dicebot wrote:
 On Friday, 21 August 2015 at 11:34:58 UTC, Steven Schveighoffer wrote:
 A MUCH better solution:

 T[] _d_arrayliteral(T)(size_t length)
It needs to be trivial wrapper which forwards to proposed
 void* _d_arrayliteralTX(size_t length, size_t sizeelem, uint flags, bool
 isshared);
Otherwise you get another binary bloat issue.
Sure: pragma(inline, true) T[] _d_arrayliteral(T)(size_t length) -Steve
Aug 21 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 21 August 2015 at 11:48:12 UTC, Steven Schveighoffer 
wrote:
 Sure:

 pragma(inline, true) T[] _d_arrayliteral(T)(size_t length)

 -Steve
Btw, are `pragma(inline, true)` function actually guaranteed to not have own code gen? :)
Aug 21 2015
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/21/15 7:57 AM, Dicebot wrote:
 On Friday, 21 August 2015 at 11:48:12 UTC, Steven Schveighoffer wrote:
 Sure:

 pragma(inline, true) T[] _d_arrayliteral(T)(size_t length)

 -Steve
Btw, are `pragma(inline, true)` function actually guaranteed to not have own code gen? :)
I have no idea. It probably should be guaranteed, because what is the point of having an "always inlined" function that generates it's own code? But if you took the address of it, it would need the code to be generated. Not sure what happens there, probably should be an error. -Steve
Aug 21 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 21 August 2015 at 12:41:17 UTC, Steven Schveighoffer 
wrote:
 I have no idea. It probably should be guaranteed, because what 
 is the point of having an "always inlined" function that 
 generates it's own code?
If it is guaranteed, almost makes me want to abuse it for this: pragma(inline, true) string foo() { if (!__ctfe) assert(false); // ... } (for compilers other than LDC)
Aug 21 2015
parent reply Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 21 August 2015 at 14:43, Dicebot via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Friday, 21 August 2015 at 12:41:17 UTC, Steven Schveighoffer wrote:

 I have no idea. It probably should be guaranteed, because what is the
 point of having an "always inlined" function that generates it's own code?
If it is guaranteed, almost makes me want to abuse it for this: pragma(inline, true) string foo() { if (!__ctfe) assert(false); // ... } (for compilers other than LDC)
That enforces that foo() is always folded at compile time, not always inlined, no?
Aug 21 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 21 August 2015 at 13:11:14 UTC, Iain Buclaw wrote:
 If it is guaranteed, almost makes me want to abuse it for this:

 pragma(inline, true)
 string foo()
 {
     if (!__ctfe)
         assert(false);
     // ...
 }

 (for compilers other than LDC)
That enforces that foo() is always folded at compile time, not always inlined, no?
And when you combine both you gets function that is always folded at compile time and does not bloat the generated object file (like it happens right now with CTFE-only functions - they are still emitted to the binary). Win. Of course, with LDC it is not an issue because they got --gc-sections working and CTFE utils get garbage collected :P
Aug 21 2015
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/21/2015 6:27 AM, Dicebot wrote:
 And when you combine both you gets function that is always folded at compile
 time and does not bloat the generated object file (like it happens right now
 with CTFE-only functions - they are still emitted to the binary). Win.
They are emitted as COMDATs, and as such are not emitted to the binary (at least on Windows, where COMDATs actually work).
Aug 21 2015
prev sibling parent reply Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 21 August 2015 at 13:57, Dicebot via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Friday, 21 August 2015 at 11:48:12 UTC, Steven Schveighoffer wrote:

 Sure:

 pragma(inline, true) T[] _d_arrayliteral(T)(size_t length)

 -Steve
Btw, are `pragma(inline, true)` function actually guaranteed to not have own code gen? :)
For compilers other than DMD, their code needs to be generated to allow the backend to inline/optimize calls away - something that I'm pretty sure is not done when calling a pragma(inline, true) function that lives in another module. Other than that, the semantics of pragma(inline, true) should guarantee that the function is never *written* to object file. Regards Iain
Aug 21 2015
parent reply Johannes Pfau <nospam example.com> writes:
Am Fri, 21 Aug 2015 15:16:01 +0200
schrieb Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com>:

 
 Other than that, the semantics of pragma(inline, true) should
 guarantee that the function is never *written* to object file.
 
This really should be documented then. If we build a shared library with pragma(inline) functions not emitting the function prevents taking the address of that function in all client code. As this is a breaking change to 'normal' inline semantics it needs to be documented. https://github.com/D-Programming-Language/dlang.org/pull/1073
Aug 22 2015
parent reply Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 22 August 2015 at 11:33, Johannes Pfau via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 Am Fri, 21 Aug 2015 15:16:01 +0200
 schrieb Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com>:

 Other than that, the semantics of pragma(inline, true) should
 guarantee that the function is never *written* to object file.
This really should be documented then. If we build a shared library with pragma(inline) functions not emitting the function prevents taking the address of that function in all client code. As this is a breaking change to 'normal' inline semantics it needs to be documented. https://github.com/D-Programming-Language/dlang.org/pull/1073
I wouldn't go as far as preventing these functions from having their address taken. In that instance, of *course* it needs to be written to object file. But it should be put in COMDAT as each external module that takes its address will have a copy of it. Regards Iain.
Aug 22 2015
next sibling parent Johannes Pfau <nospam example.com> writes:
Am Sat, 22 Aug 2015 14:47:34 +0200
schrieb Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com>:

 On 22 August 2015 at 11:33, Johannes Pfau via Digitalmars-d <
 digitalmars-d puremagic.com> wrote:
 
 Am Fri, 21 Aug 2015 15:16:01 +0200
 schrieb Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com>:

 Other than that, the semantics of pragma(inline, true) should
 guarantee that the function is never *written* to object file.
This really should be documented then. If we build a shared library with pragma(inline) functions not emitting the function prevents taking the address of that function in all client code. As this is a breaking change to 'normal' inline semantics it needs to be documented. https://github.com/D-Programming-Language/dlang.org/pull/1073
I wouldn't go as far as preventing these functions from having their address taken. In that instance, of *course* it needs to be written to object file. But it should be put in COMDAT as each external module that takes its address will have a copy of it. Regards Iain.
That's indeed a better solution.
Aug 22 2015
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/22/2015 5:47 AM, Iain Buclaw via Digitalmars-d wrote:
 But it should be put in COMDAT
And it is.
Aug 22 2015
prev sibling parent reply Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 21 August 2015 at 13:35, Steven Schveighoffer via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On 8/21/15 7:22 AM, Iain Buclaw via Digitalmars-d wrote:

 Where removing RTTI disables D feature's in a compromising way, I'd
 start by questioning the why.

 Eg:  Why does array literals need RTTI?  Looking at _d_arrayliteralTX
 implementation, it only does the following with the given TypeInfo
 provided:

 - Get the array element size (this is known at compile time)
 - Get the array element type flags (calculated during the codegen stage,
 but otherwise known at compile time)
 - Test if the TypeInfo is derived from TypeInfo_Shared (can be done at -
 you guessed it - compile time by peeking through the baseClass linked
 list for a given TypeInfo type we are passing).

 So we have this function that accepts a TypeInfo, but doesn't really
 *need* to at all.

 void* _d_arrayliteralTX(size_t length, size_t sizeelem, uint flags, bool
 isshared);

 Just putting it out there....
I strongly suggest we *don't* go this route. This means that any changes to what is required for the runtime to properly construct an array requires a compiler change. A MUCH better solution: T[] _d_arrayliteral(T)(size_t length) Also, isn't the typeinfo now stored by the GC so it can call the dtor? Perhaps that is done in the filling of the array literal, but I would be surprised as this is a GC feature.
I only looked at 2.066.1, the runtime implementation did not pass the typeinfo to the GC.
Aug 22 2015
parent reply "Mike" <none none.com> writes:
On Saturday, 22 August 2015 at 10:11:24 UTC, Iain Buclaw wrote:

 A MUCH better solution:

 T[] _d_arrayliteral(T)(size_t length)

 Also, isn't the typeinfo now stored by the GC so it can call 
 the dtor? Perhaps that is done in the filling of the array 
 literal, but I would be surprised as this is a GC feature.
I only looked at 2.066.1, the runtime implementation did not pass the typeinfo to the GC.
_d_arrayliteralTX eventually calls structTypeInfoSize() which, according to https://github.com/D-Programming-Language/druntime/blob/master/src rt/lifetime.d#L214, is used to determine the size of TypeInfo so it can be stored by the GC, as Steven said. Mike
Aug 26 2015
parent reply Iain Buclaw via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 26 August 2015 at 15:14, Mike via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 On Saturday, 22 August 2015 at 10:11:24 UTC, Iain Buclaw wrote:

 A MUCH better solution:
 T[] _d_arrayliteral(T)(size_t length)

 Also, isn't the typeinfo now stored by the GC so it can call the dtor?
 Perhaps that is done in the filling of the array literal, but I would be
 surprised as this is a GC feature.


 I only looked at 2.066.1, the runtime implementation did not pass the
typeinfo to the GC.
_d_arrayliteralTX eventually calls structTypeInfoSize() which, according to https://github.com/D-Programming-Language/druntime/blob/master/src/rt/lifetime.d#L214, is used to determine the size of TypeInfo so it can be stored by the GC, as Steven said. Mike
Well, I have no control over what the library maintainers in DMD want to do in their runtime, but all is working fine without doing that in my camp.
Aug 26 2015
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/26/15 10:50 AM, Iain Buclaw via Digitalmars-d wrote:
 On 26 August 2015 at 15:14, Mike via Digitalmars-d
 <digitalmars-d puremagic.com <mailto:digitalmars-d puremagic.com>> wrote:

     On Saturday, 22 August 2015 at 10:11:24 UTC, Iain Buclaw wrote:

             A MUCH better solution:

             T[] _d_arrayliteral(T)(size_t length)

             Also, isn't the typeinfo now stored by the GC so it can call
             the dtor? Perhaps that is done in the filling of the array
             literal, but I would be surprised as this is a GC feature.


         I only looked at 2.066.1, the runtime implementation did not
         pass the typeinfo to the GC.


     _d_arrayliteralTX eventually calls structTypeInfoSize() which,
     according to
     https://github..com/D-Programming-Language/druntime/blob/master/src/rt/lifetime.d#L214
     <https://github.com/D-Programming-Language/druntime/blob/master/src/rt/lifetime.d#L214>,
     is used to determine the size of TypeInfo so it can be stored by the
     GC, as Steven said.

     Mike


 Well, I have no control over what the library maintainers in DMD want to
 do in their runtime, but all is working fine without doing that in my camp.
The change was to make it so struct dtors are called by the GC. -Steve
Aug 27 2015
prev sibling next sibling parent reply "Kagamin" <spam here.lot> writes:
On Friday, 21 August 2015 at 11:03:09 UTC, Mike wrote:
 * postblit - 
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR918
 * destructor - 
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR1039
Looks like these are generated for fixed sized array of structs in a struct.
 * slicing - 
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R11857
Can't even understand, what is this. Array op? But array ops are handled just above.
Aug 21 2015
parent Johannes Pfau <nospam example.com> writes:
Am Fri, 21 Aug 2015 11:46:21 +0000
schrieb "Kagamin" <spam here.lot>:

 On Friday, 21 August 2015 at 11:03:09 UTC, Mike wrote:
 * postblit - 
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR918
 * destructor - 
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR1039
Looks like these are generated for fixed sized array of structs in a struct.
 * slicing - 
 https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R11857
Can't even understand, what is this. Array op? But array ops are handled just above.
If you do 'array[] = n' the compiler calls one of _d_arraysetctor, _d_arraysetassign, _d_arrayassign, _d_arrayctor or _d_arraycopy. http://wiki.dlang.org/Runtime_Hooks The calls basically copy n to the array and call the postblit for every value in array[]. They also call 'TypeInfo.destroy' (destructor) on old values before overwriting. arraycopy doesn't use TypeInfo. The rest could be easily rewritten to be templated* or completely compiler generated. * I'm not sure if we support manually accessing the postblit of a type. OTOH if these functions were templated the compiler would likely emit the correct postblit/destroy calls automatically.
Aug 22 2015
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/21/15 7:03 AM, Mike wrote:
 On Friday, 21 August 2015 at 08:11:37 UTC, Kagamin wrote:
 On Friday, 21 August 2015 at 06:00:44 UTC, Mike wrote:
 Disabling TypeInfo forces one to compromise on slicing, postblit
Why slicing and postblit would need typeinfo?
See below for the source code. Some obvious, some not. * dynamic cast - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-83bcb64558f947e39f87d7435709dfe7R364 * array literal - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-bed7d2226948b1e098749985d7a60633R2353 * postblit - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR918 * destructor - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-1f51c84492753de4c1863d02e24318bbR1039, https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-867588d7078efd0364c256152fb5a2e7R2053 * new - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R5091 * AAs - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R10710 * slicing - https://github.com/D-Programming-GDC/GDC/pull/100/files?diff=unified#diff-5960d486a42197785b9eee4ba95c6b95R11857 etc... Disabling TypeInfo requires quite a compromise on D's features. I want TypeInfo, I just don't want dead code. Mike
Thanks for this list. I think these need to be fixed (by replacing indirect-calls-based code with templates) regardless of where we go with TypeInfo. There's a fair amount of druntime code that suffers from being written before templates or in avoidance thereof. -- Andrei
Aug 21 2015
next sibling parent "Martin Nowak" <code dawg.eu> writes:
On Friday, 21 August 2015 at 13:47:49 UTC, Andrei Alexandrescu 
wrote:
 Thanks for this list. I think these need to be fixed (by 
 replacing indirect-calls-based code with templates) regardless 
 of where we go with TypeInfo. There's a fair amount of druntime 
 code that suffers from being written before templates or in 
 avoidance thereof. -- Andrei
Yes, it's a major pain and a source for many incorrect attributes.
Aug 22 2015
prev sibling parent "Mike" <none none.com> writes:
On Friday, 21 August 2015 at 13:47:49 UTC, Andrei Alexandrescu 
wrote:

 I think these need to be fixed (by replacing 
 indirect-calls-based code with templates) regardless of where 
 we go with TypeInfo. There's a fair amount of druntime code 
 that suffers from being written before templates or in 
 avoidance thereof. -- Andrei
For whatever it's worth, below is a list of druntime functions that take TypeInfo as a parameter. My immediate need is to make it possible for an -fno-rtti switch to be added to the compiler with as little compromise as possible. In general, I'm not actually trying disable D features, even those that I don't actually need. I only need to remove dead code. If -fno-rtti is the best I can hope for, than I'll take it. Perhaps templating some of these functions will make an -fno-rtti switch more viable. I'm judging from the comments in this thread that there may be additional benefits. Would submitting pull requests towards this goal be a distraction from current priorities? Should I wait until after DDMD is out? Mike \core\memory.d 143 extern (C) void gc_addRange( in void* p, size_t sz, const TypeInfo ti = null ) nothrow nogc; 364 static void* malloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) pure nothrow 390 static BlkInfo qalloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) pure nothrow 417 static void* calloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) pure nothrow 457 static void* realloc( void* p, size_t sz, uint ba = 0, const TypeInfo ti = null ) pure nothrow 501 static size_t extend( void* p, size_t mx, size_t sz, const TypeInfo ti = null ) pure nothrow 754 static void addRange( in void* p, size_t sz, const TypeInfo ti = null ) nogc nothrow /* FIXME pure */ \object.d 1761 inout(void)[] _aaValues(inout void* p, in size_t keysize, in size_t valuesize, const TypeInfo tiValArray) pure nothrow; 1762 inout(void)[] _aaKeys(inout void* p, in size_t keysize, const TypeInfo tiKeyArray) pure nothrow; 1778 int _aaEqual(in TypeInfo tiRaw, in void* e1, in void* e2); 1779 hash_t _aaGetHash(in void* aa, in TypeInfo tiRaw) nothrow; 2794 extern (C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow; 2795 extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void *arrptr) pure nothrow; 3231 private extern (C) void[] _d_newarrayU(const TypeInfo ti, size_t length) pure nothrow; \core\stdc\stdarg.d 60 void va_arg()(ref va_list ap, TypeInfo ti, void* parmn) 131 void va_arg()(ref va_list ap, TypeInfo ti, void* parmn) 345 void va_arg()(va_list apx, TypeInfo ti, void* parmn) \gc\proxy.d 58 void function(void*, size_t, const TypeInfo ti) gc_addRange; 184 void* gc_malloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 191 BlkInfo gc_qalloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 203 void* gc_calloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 210 void* gc_realloc( void* p, size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 217 size_t gc_extend( void* p, size_t mx, size_t sz, const TypeInfo ti = null ) nothrow 282 void gc_addRange( void* p, size_t sz, const TypeInfo ti = null ) nothrow \gcstub\gc.d 65 extern (C) void function(void*, size_t, const TypeInfo ti) gc_addRange; 184 extern (C) void* gc_malloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) 197 extern (C) BlkInfo gc_qalloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) 210 extern (C) void* gc_calloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) 223 extern (C) void* gc_realloc( void* p, size_t sz, uint ba = 0, const TypeInfo ti = null ) 236 extern (C) size_t gc_extend( void* p, size_t mx, size_t sz, const TypeInfo ti = null ) 293 extern (C) void gc_addRange( void* p, size_t sz, const TypeInfo ti = null ) \rt\arrayassign.d 27 extern (C) void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to) 49 extern (C) void[] _d_arrayassign_l(TypeInfo ti, void[] src, void[] dst, void* ptmp) 141 extern (C) void[] _d_arrayassign_r(TypeInfo ti, void[] src, void[] dst, void* ptmp) 167 extern (C) void[] _d_arrayctor(TypeInfo ti, void[] from, void[] to) 205 extern (C) void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti) 236 extern (C) void* _d_arraysetctor(void* p, void* value, int count, TypeInfo ti) \rt\aaA.d 438 extern (C) inout(void[]) _aaValues(inout AA aa, in size_t keysz, in size_t valsz, const TypeInfo tiValueArray) pure nothrow 461 extern (C) inout(void[]) _aaKeys(inout AA aa, in size_t keysz, const TypeInfo tiKeyArray) pure nothrow 567 extern (C) int _aaEqual(in TypeInfo tiRaw, in AA aa1, in AA aa2) 597 extern (C) hash_t _aaGetHash(in AA* aa, in TypeInfo tiRaw) nothrow \rt\adi.d 24 extern (C) void[] _adSort(void[] a, TypeInfo ti); 365 extern (C) int _adEq(void[] a1, void[] a2, TypeInfo ti) 386 extern (C) int _adEq2(void[] a1, void[] a2, TypeInfo ti) 415 extern (C) int _adCmp(void[] a1, void[] a2, TypeInfo ti) 445 extern (C) int _adCmp2(void[] a1, void[] a2, TypeInfo ti) \gc\gc.d 484 void *malloc(size_t size, uint bits = 0, size_t *alloc_size = null, const TypeInfo ti = null) nothrow 516 private void *mallocNoSync(size_t size, uint bits, ref size_t alloc_size, const TypeInfo ti = null) nothrow 546 void *calloc(size_t size, uint bits = 0, size_t *alloc_size = null, const TypeInfo ti = null) nothrow 578 void *realloc(void *p, size_t size, uint bits = 0, size_t *alloc_size = null, const TypeInfo ti = null) nothrow 603 private void *reallocNoSync(void *p, size_t size, ref uint bits, ref size_t alloc_size, const TypeInfo ti = null) nothrow 753 size_t extend(void* p, size_t minsize, size_t maxsize, const TypeInfo ti = null) nothrow 766 private size_t extendNoSync(void* p, size_t minsize, size_t maxsize, const TypeInfo ti = null) nothrow 1178 void addRange(void *p, size_t sz, const TypeInfo ti = null) nothrow nogc 1568 void addRange(void *pbot, void *ptop, const TypeInfo ti) nothrow nogc 1826 void* bigAlloc(size_t size, ref size_t alloc_size, uint bits, const TypeInfo ti = null) nothrow \rt\qsort.d 26 extern (C) void[] _adSort(void[] a, TypeInfo ti) 41 extern (C) void[] _adSort(void[] a, TypeInfo ti) 56 extern (C) void[] _adSort(void[] a, TypeInfo ti) 68 private TypeInfo tiglobal; 70 extern (C) void[] _adSort(void[] a, TypeInfo ti) \rt\typeinfo\ti_Aint.d 19 extern (C) void[] _adSort(void[] a, TypeInfo ti); \rt\tracegc.d 87 extern (C) void[] _d_newarrayT(const TypeInfo ti, size_t length); 88 extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length); 89 extern (C) void[] _d_newarraymTX(const TypeInfo ti, size_t[] dims); 90 extern (C) void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims); 109 extern (C) void[] _d_newarrayTTrace(string file, int line, string funcname, const TypeInfo ti, size_t length) 125 extern (C) void[] _d_newarrayiTTrace(string file, int line, string funcname, const TypeInfo ti, size_t length) 141 extern (C) void[] _d_newarraymTXTrace(string file, int line, string funcname, const TypeInfo ti, size_t[] dims) 160 extern (C) void[] _d_newarraymiTXTrace(string file, int line, string funcname, const TypeInfo ti, size_t[] dims) 179 extern (C) void* _d_newitemTTrace(string file, int line, string funcname, in TypeInfo ti) 194 extern (C) void* _d_newitemiTTrace(string file, int line, string funcname, in TypeInfo ti) 214 extern (C) void _d_delstruct(void** p, TypeInfo_Struct inf) 274 extern (C) void _d_delstructTrace(string file, int line, string funcname, void** p, TypeInfo_Struct inf) 319 extern (C) void* _d_arrayliteralTX(const TypeInfo ti, size_t length); 322 extern (C) void* _d_arrayliteralTXTrace(string file, int line, string funcname, const TypeInfo ti, size_t length) 358 extern (C) byte[] _d_arraycatT(const TypeInfo ti, byte[] x, byte[] y); 359 extern (C) void[] _d_arraycatnTX(const TypeInfo ti, byte[][] arrs); 361 extern (C) byte[] _d_arraycatTTrace(string file, int line, string funcname, const TypeInfo ti, byte[] x, byte[] y) 378 extern (C) void[] _d_arraycatnTXTrace(string file, int line, string funcname, const TypeInfo ti, byte[][] arrs) 397 extern (C) void[] _d_arrayappendT(const TypeInfo ti, ref byte[] x, byte[] y); 398 extern (C) byte[] _d_arrayappendcTX(const TypeInfo ti, ref byte[] px, size_t n); 402 extern (C) void[] _d_arrayappendTTrace(string file, int line, string funcname, const TypeInfo ti, ref byte[] x, byte[] y) 419 extern (C) byte[] _d_arrayappendcTXTrace(string file, int line, string funcname, const TypeInfo ti, ref byte[] px, size_t n) 480 extern (C) void[] _d_arraysetlengthT(const TypeInfo ti, size_t newlength, void[]* p); 481 extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p); 483 extern (C) void[] _d_arraysetlengthTTrace(string file, int line, string funcname, const TypeInfo ti, size_t newlength, void[]* p) 500 extern (C) void[] _d_arraysetlengthiTTrace(string file, int line, string funcname, const TypeInfo ti, size_t newlength, void[]* p) \rt\lifetime.d 180 extern (C) void _d_delstruct(void** p, TypeInfo_Struct inf) 215 size_t structTypeInfoSize(const TypeInfo ti) pure nothrow nogc 269 bool __setArrayAllocLength(ref BlkInfo info, size_t newlength, bool isshared, const TypeInfo tinext, size_t oldlength = ~0) pure nothrow 374 size_t __arrayAllocLength(ref BlkInfo info, const TypeInfo tinext) pure nothrow 398 size_t __arrayPad(size_t size, const TypeInfo tinext) nothrow pure trusted 407 BlkInfo __arrayAlloc(size_t arrsize, const TypeInfo ti, const TypeInfo tinext) nothrow pure 421 BlkInfo __arrayAlloc(size_t arrsize, ref BlkInfo info, const TypeInfo ti, const TypeInfo tinext) 631 extern(C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) /+nothrow+/ 670 package bool hasPostblit(in TypeInfo ti) 675 void __doPostblit(void *ptr, size_t len, const TypeInfo ti) 712 extern(C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* p) 882 extern (C) void[] _d_newarrayU(const TypeInfo ti, size_t length) pure nothrow 941 extern (C) void[] _d_newarrayT(const TypeInfo ti, size_t length) pure nothrow 954 extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length) pure nothrow 987 void[] _d_newarrayOpT(alias op)(const TypeInfo ti, size_t[] dims) 1028 extern (C) void[] _d_newarraymTX(const TypeInfo ti, size_t[] dims) 1044 extern (C) void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims) 1413 extern (C) void[] _d_arraysetlengthT(const TypeInfo ti, size_t newlength, void[]* p) 1597 extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p) 1794 extern (C) void[] _d_arrayappendT(const TypeInfo ti, ref byte[] x, byte[] y) 1894 byte[] _d_arrayappendcTX(const TypeInfo ti, ref byte[] px, size_t n) 2076 extern (C) byte[] _d_arraycatT(const TypeInfo ti, byte[] x, byte[] y) 2141 extern (C) void[] _d_arraycatnTX(const TypeInfo ti, byte[][] arrs) 2180 void* _d_arrayliteralTX(const TypeInfo ti, size_t length)
Aug 22 2015
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Friday, 21 August 2015 at 08:11:37 UTC, Kagamin wrote:
 On Friday, 21 August 2015 at 06:00:44 UTC, Mike wrote:
 Disabling TypeInfo forces one to compromise on slicing, 
 postblit
Why slicing and postblit would need typeinfo?
Because the runtime implementation is broken and rely on it instead of templates.
Aug 21 2015
prev sibling parent "sclytrack" <sclytrack fake.com> writes:
On Friday, 21 August 2015 at 05:24:52 UTC, BBasile wrote:
 On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the 
 program. To make it work, though, every class in the program 
 has to have a TypeInfo generated for it:
...
 Other alternatives would be a pragma or an attribute to disable 
 TypeInfo generation.
  NoTI.
1. "Since it is compiled in the {$M+} state, the compiler generates RTTI (Run-Time Type Information) for it and all classes that descend from it." http://freepascal.org/docs-html/rtl/classes/tpersistent.html 2. "Published properties are included in RTTI, public properties aren't" http://stackoverflow.com/questions/3157648/whats-the-difference-between-public-and-published-class-members-in-delphi
Aug 20 2015
prev sibling next sibling parent "Paolo Invernizzi" <paolo.invernizzi no.address> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the 
 program. To make it work, though, every class in the program 
 has to have a TypeInfo generated for it. This leads to bloat:

   https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory 
 be able to instantiate classes marked as 'export'. This only 
 makes sense anyway.

 What do you think?
+1000!
Aug 20 2015
prev sibling next sibling parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
On 8/21/2015 5:06 PM, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the program. To
 make it work, though, every class in the program has to have a TypeInfo
 generated for it. This leads to bloat:

    https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory be able to
 instantiate classes marked as 'export'. This only makes sense anyway.

 What do you think?
I need to look over my code that I've written for my to be web application server. But: I'm a little concerned that if there is no alternative we won't be able to seriously be able to have a web application server ala JSP servlet style. So while export may work, perhaps a slightly different approach. If an interface/class is marked as export, it gets inherited. So an child class/implementation would also be export because a super interface/class was export. This would make me a lot happier.
Aug 20 2015
parent "Rikki Cattermole" <alphaglosined gmail.com> writes:
On Friday, 21 August 2015 at 06:24:34 UTC, Rikki Cattermole wrote:
 On 8/21/2015 5:06 PM, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the 
 program. To
 make it work, though, every class in the program has to have a 
 TypeInfo
 generated for it. This leads to bloat:

    https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory 
 be able to
 instantiate classes marked as 'export'. This only makes sense 
 anyway.

 What do you think?
I need to look over my code that I've written for my to be web application server. But: I'm a little concerned that if there is no alternative we won't be able to seriously be able to have a web application server ala JSP servlet style. So while export may work, perhaps a slightly different approach. If an interface/class is marked as export, it gets inherited. So an child class/implementation would also be export because a super interface/class was export. This would make me a lot happier.
I've had a look at it finally. This would definitely effect me. Since TypeInfo_Class would still need to exist to access .init. Humpth yes, it would be definitely desirable for me as the framework author to say every class that inherits from this interface must be visible to me. If it is not it is useless. Transients would be desired in this use case. That way the average developer wouldn't have to worry about this behaviour.
Aug 23 2015
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2015-08-21 07:06, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the program. To
 make it work, though, every class in the program has to have a TypeInfo
 generated for it. This leads to bloat:

    https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory be able to
 instantiate classes marked as 'export'. This only makes sense anyway.

 What do you think?
I think, or rather know, that this will break serialization, i.e. my library Orange [1]. I really like that one doesn't need to register a class to be able to (de)serialize it. I can't believe this change is purposed that will clearly break valid code. But at the same time there are other breaking changes you refuse to do that would fix design flaws in the language. I still remember your rant about your old D1 project that didn't compile with the latest D2 compiler. [1] https://github.com/jacob-carlborg/orange -- /Jacob Carlborg
Aug 20 2015
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/20/2015 11:40 PM, Jacob Carlborg wrote:
 I think, or rather know, that this will break serialization, i.e. my library
 Orange [1]. I really like that one doesn't need to register a class to be able
 to (de)serialize it.

 I can't believe this change is purposed that will clearly break valid code.
A large purpose of starting this thread is to find out in advance what sort of breakage would be likely, and explore ways to mitigate that breakage.
 But at the same time there are other breaking changes you refuse to do that
would
 fix design flaws in the language.
As with everything, it's cost/benefit. Changing isnan to isNaN is an example of all cost and no benefit. I've explained the benefits of changing factory() a couple times in this thread. I believe the benefits are significant, including the benefit of making D viable for use in embedded systems.
 I still remember your rant about your old D1 project that didn't compile with
 the latest D2 compiler.
Many of the breaking changes were gratuitous (all cost and no benefit), and some required rewrites so extensive I (along with invaluable help from Dmitry) created undeaD to deal with it: https://github.com/DigitalMars/undeaD
Aug 21 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 21 August 2015 at 21:50:21 UTC, Walter Bright wrote:
 As with everything, it's cost/benefit. Changing isnan to isNaN 
 is an example of all cost and no benefit.

 I've explained the benefits of changing factory() a couple 
 times in this thread. I believe the benefits are significant, 
 including the benefit of making D viable for use in embedded 
 systems.
This is fundamentally flawed way of thinking which only confirms my feeling that my last DConf talk was a complete waste. You completely ignore what those changes mean to your users by making such statements. Changing isnan to isNaN is a small benefit (better internal structure and consistency is important) but it also comes at tiny, almost insignificant costs. It doesn't cause any immediate breakage and can be adjusted to at any moment with 1 simple search/replace. It is a best kind of change you can have, tier 1 ("good") in my classification. Proposed change in Object.factory, on the other hand, is the worst possible kind of breaking changes you can ever make (tier 3, "ugly") - it changes program semantics silently at runtime with no errors and can't be adjusted to in automated manner, requiring full reimplementation of some designs. Cost of this change is huge, it will take no less than several full working days to fix everything. Benefits are also not small - Mike use case is very important. Yet in current proposed form ration of cost/benefit is much much worse than one of isnan/isNaN - simply because how big costs are. To make the change more acceptable you can take one of two possible paths: 1) make more benefits, for example by improving `export` definition and unifying its semantics between platforms (see also attribute inference / WPO proposals by Martin) 2) reduce costs by providing compiler diagnostics for transition and enabling similar designs at CT (see the issue I have linked earlier) Doing both is perfection, of course.
Aug 23 2015
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/23/2015 2:27 AM, Dicebot wrote:
 Changing isnan to isNaN is a small benefit (better internal structure and
 consistency is important) but it also comes at tiny, almost insignificant
costs.
 It doesn't cause any immediate breakage and can be adjusted to at any moment
 with 1 simple search/replace. It is a best kind of change you can have, tier 1
 ("good") in my classification.
I agree the cost is small, but the benefit is zero. Yes, I understand you (and others) don't agree with my estimation of the benefit. I don't see much point in debating that one further, it's a done deal.
 Proposed change in Object.factory, on the other hand, is the worst possible
kind
 of breaking changes you can ever make (tier 3, "ugly") - it changes program
 semantics silently at runtime with no errors and can't be adjusted to in
 automated manner, requiring full reimplementation of some designs. Cost of this
 change is huge, it will take no less than several full working days to fix
 everything.

 Benefits are also not small - Mike use case is very important. Yet in current
 proposed form ration of cost/benefit is much much worse than one of isnan/isNaN
 - simply because how big costs are.

 To make the change more acceptable you can take one of two possible paths:

 1) make more benefits, for example by improving `export` definition and
unifying
 its semantics between platforms (see also attribute inference / WPO proposals
by
 Martin)
 2) reduce costs by providing compiler diagnostics for transition and enabling
 similar designs at CT (see the issue I have linked earlier)

 Doing both is perfection, of course.
The point of this thread is to investigate the various ways of mitigating the costs and figure out the best way forward.
Aug 23 2015
prev sibling next sibling parent reply "Benjamin Thaut" <code benjamin-thaut.de> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the 
 program. To make it work, though, every class in the program 
 has to have a TypeInfo generated for it. This leads to bloat:

   https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory 
 be able to instantiate classes marked as 'export'. This only 
 makes sense anyway.

 What do you think?
I don't think this is a good idea. That's just abusing a already existing keyword. Export basically means "Make this function or class visible across shared library boundaries". I don't see how this connects to the object factory. Maybe I want to instantiate a class via the factory that should not be visible across a shared library boundary (e.g. to keep the interface of a shared library minimal). Please also consider that as export means dllexport and dllimport at the same time (on Windows) classes marked with export will inflict additional runtime overhead due to the double indirection needed for dlls and due to the fact that you sometimes don't know if the class resides in a different binary then the one your are currently in. This runtime overhead even occurs for purely static builds, as the compiler can't know if the generated code uses some shared library or not. (unless we add a specific compiler switch for it, like -onlyStatic which many people will not be a fan of. And no the -shared flag doesn't help as executables are build without -shared and might still use shared libraries) Given how limited object.factory is I would just vote that we kill it completely. Every time I wanted to use it, it was to limited and I ended up building my own reflection / factory mechanism. Even though you rejected my proposal for making export a attribute instead of a visibility level, I think that once a broader set of contributors sees the issue behind export being a protection level the demand will be high to make export an attribute. Giving export a additional meaning now will only complicate this. Tldr: As broken as export currently is we shouldn't be using it for anything else. Kind Regards Benjamin Thaut
Aug 21 2015
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2015-08-21 09:24, Benjamin Thaut wrote:

 Given how limited object.factory is I would just vote that we kill it
 completely. Every time I wanted to use it, it was to limited and I ended
 up building my own reflection / factory mechanism.
How is it limiting? That it only works with default constructors? I don't think that underlying ClassInfo.find is limiting, which is where the interesting part happens. I'm pretty sure that Object.factory could be extended to support non-default constructors, if that makes it less limiting. -- /Jacob Carlborg
Aug 21 2015
parent reply "Benjamin Thaut" <code benjamin-thaut.de> writes:
On Friday, 21 August 2015 at 08:49:37 UTC, Jacob Carlborg wrote:
 How is it limiting? That it only works with default 
 constructors? I don't think that underlying ClassInfo.find is 
 limiting, which is where the interesting part happens. I'm 
 pretty sure that Object.factory could be extended to support 
 non-default constructors, if that makes it less limiting.
Yes, the usual problem was that it only works with default constructors. Also it doesn't work with nested classes e.g. class Outer { class Inner { } } I don't know if that is fixed now.
Aug 21 2015
parent Jacob Carlborg <doob me.com> writes:
On 2015-08-21 10:52, Benjamin Thaut wrote:

 Yes, the usual problem was that it only works with default constructors.
 Also it doesn't work with nested classes e.g.

 class Outer
 {
    class Inner
    {
    }
 }

 I don't know if that is fixed now.
It sounds like both of these could be fixed. BTW, in my serialization library I don't even call the constructor so I don't have that problem. -- /Jacob Carlborg
Aug 21 2015
prev sibling next sibling parent Johannes Pfau <nospam example.com> writes:
Am Fri, 21 Aug 2015 07:24:58 +0000
schrieb "Benjamin Thaut" <code benjamin-thaut.de>:

 I don't think this is a good idea. That's just abusing a already 
 existing keyword. Export basically means "Make this function or 
 class visible across shared library boundaries". 
+1. I think we should be very careful when reusing a keyword which isn't fully specified.
Aug 21 2015
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/21/2015 12:24 AM, Benjamin Thaut wrote:
 Export basically means "Make this function or class visible across
 shared library boundaries". I don't see how this connects to the object
factory.
Object.factory() only has a point when it is used to instantiate classes in a DLL/so. It fits in nicely with export.
Aug 21 2015
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 21-Aug-2015 13:44, Walter Bright wrote:
 On 8/21/2015 12:24 AM, Benjamin Thaut wrote:
 Export basically means "Make this function or class visible across
 shared library boundaries". I don't see how this connects to the
 object factory.
Object.factory() only has a point when it is used to instantiate classes in a DLL/so. It fits in nicely with export.
Still abusing visibility keyword is probably bad idea, it's already tricky with private implying final or some such nonsense. Just add ObjectFactory UDA to object.d and be done with it? -- Dmitry Olshansky
Aug 21 2015
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2015-08-21 12:44, Walter Bright wrote:

 Object.factory() only has a point when it is used to instantiate classes
 in a DLL/so. It fits in nicely with export.
It's useful for deserialization as well. -- /Jacob Carlborg
Aug 21 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 21 August 2015 at 13:18:17 UTC, Jacob Carlborg wrote:
 On 2015-08-21 12:44, Walter Bright wrote:

 Object.factory() only has a point when it is used to 
 instantiate classes
 in a DLL/so. It fits in nicely with export.
It's useful for deserialization as well.
Btw we use it for high-level testing framework - will be rather hard to move that to compile-time approach until some reflection bugs gets fixed.
Aug 21 2015
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/21/2015 6:29 AM, Dicebot wrote:
 On Friday, 21 August 2015 at 13:18:17 UTC, Jacob Carlborg wrote:
 On 2015-08-21 12:44, Walter Bright wrote:

 Object.factory() only has a point when it is used to instantiate classes
 in a DLL/so. It fits in nicely with export.
It's useful for deserialization as well.
Btw we use it for high-level testing framework - will be rather hard to move that to compile-time approach
It's good to hear of use cases for Object.factory.
 until some reflection bugs gets fixed.
Bugzilla issues? (You knew that was coming!)
Aug 21 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 21 August 2015 at 20:28:47 UTC, Walter Bright wrote:
 Btw we use it for high-level testing framework - will be 
 rather hard to move
 that to compile-time approach
It's good to hear of use cases for Object.factory.
If you want details it is special library for black box testing applications by spawning them as external processes and interacting with their shell/network API. To minimize boilerplate test scenarios are derived from special TestCase class and test runner finds all classes that derive from TestCase automatically. Marking them all as export will be inconvenient but is possible - but I'd like to get something useful in return, like well-defined and working export for example.
 until some reflection bugs gets fixed.
Bugzilla issues? (You knew that was coming!)
https://issues.dlang.org/show_bug.cgi?id=11595 is the main offender. Currently the task 'find all symbols with a given trait in the whole program' can't be implemented at CT.
Aug 22 2015
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/22/2015 2:42 AM, Dicebot wrote:
 On Friday, 21 August 2015 at 20:28:47 UTC, Walter Bright wrote:
 Btw we use it for high-level testing framework - will be rather hard to move
 that to compile-time approach
It's good to hear of use cases for Object.factory.
If you want details it is special library for black box testing applications by spawning them as external processes and interacting with their shell/network API. To minimize boilerplate test scenarios are derived from special TestCase class and test runner finds all classes that derive from TestCase automatically. Marking them all as export will be inconvenient but is possible - but I'd like to get something useful in return, like well-defined and working export for example.
I'm not sure how export would help on Linux.
 until some reflection bugs gets fixed.
Bugzilla issues? (You knew that was coming!)
https://issues.dlang.org/show_bug.cgi?id=11595 is the main offender. Currently the task 'find all symbols with a given trait in the whole program' can't be implemented at CT.
Thanks!
Aug 22 2015
next sibling parent reply "David Nadlinger" <code klickverbot.at> writes:
On Saturday, 22 August 2015 at 20:14:59 UTC, Walter Bright wrote:
 I'm not sure how export would help on Linux.
One of the use cases for export on Linux would be to set the ELF visibility based on it. Emitting all the symbols with default visibility, like we currently do, leads to size and load time problems with large libraries. Big C++ projects are plagued regularly by this (cf. "-fvisibility=hidden"). — David
Aug 22 2015
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/22/2015 1:22 PM, David Nadlinger wrote:
 On Saturday, 22 August 2015 at 20:14:59 UTC, Walter Bright wrote:
 I'm not sure how export would help on Linux.
One of the use cases for export on Linux would be to set the ELF visibility based on it. Emitting all the symbols with default visibility, like we currently do, leads to size and load time problems with large libraries. Big C++ projects are plagued regularly by this (cf. "-fvisibility=hidden").
A bugzilla enhancement request for this would be nice.
Aug 22 2015
parent reply "David Nadlinger" <code klickverbot.at> writes:
On Saturday, 22 August 2015 at 21:56:25 UTC, Walter Bright wrote:
 On 8/22/2015 1:22 PM, David Nadlinger wrote:
 One of the use cases for export on Linux would be to set the 
 ELF visibility
 based on it. Emitting all the symbols with default visibility, 
 like we currently
 do, leads to size and load time problems with large libraries. 
 Big C++ projects
 are plagued regularly by this (cf. "-fvisibility=hidden").
A bugzilla enhancement request for this would be nice.
https://issues.dlang.org/show_bug.cgi?id=9893 – David
Aug 22 2015
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 22 August 2015 at 22:08:50 UTC, David Nadlinger 
wrote:
 A bugzilla enhancement request for this would be nice.
https://issues.dlang.org/show_bug.cgi?id=9893
The common saying "if it isn't in bugzilla it is forgotten" seems quite silly when so much that IS in bugzilla is forgotten all the same.
Aug 22 2015
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/22/2015 3:41 PM, Adam D. Ruppe wrote:
 The common saying "if it isn't in bugzilla it is forgotten" seems quite silly
 when so much that IS in bugzilla is forgotten all the same.
Lots of people, like Daniel and Kenji and Vladimir and Martin, etc., go through Bugzilla looking for things to fix. I don't know anyone combing through the 300,000 messages in this n.g. looking for vaguely described complaints to fix. Furthermore, the changelog for each release shows hundreds of bugzilla issues fixed, and 0 newsgroup complaints fixed.
Aug 22 2015
prev sibling parent reply "Benjamin Thaut" <code benjamin-thaut.de> writes:
On Saturday, 22 August 2015 at 20:22:58 UTC, David Nadlinger 
wrote:
 On Saturday, 22 August 2015 at 20:14:59 UTC, Walter Bright 
 wrote:
 I'm not sure how export would help on Linux.
One of the use cases for export on Linux would be to set the ELF visibility based on it. Emitting all the symbols with default visibility, like we currently do, leads to size and load time problems with large libraries. Big C++ projects are plagued regularly by this (cf. "-fvisibility=hidden"). — David
The good news is, once I'm done with my windows DLL work the code can be trivialy reused to make export control the visibility of symbols on linux as well. Kind Regards Benjamin Thaut
Aug 23 2015
next sibling parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 8/24/2015 1:09 AM, Benjamin Thaut wrote:
 The good news is, once I'm done with my windows DLL work the code can be
 trivialy reused to make export control the visibility of symbols on
 linux as well.

 Kind Regards
 Benjamin Thaut
Wait we are getting almost full blown DLL support on Windows? Yuppie!
Aug 23 2015
prev sibling parent "Benjamin Thaut" <code benjamin-thaut.de> writes:
On Sunday, 23 August 2015 at 13:09:46 UTC, Benjamin Thaut wrote:
 The good news is, once I'm done with my windows DLL work the 
 code can be trivialy reused to make export control the 
 visibility of symbols on linux as well.

 Kind Regards
 Benjamin Thaut
But then you have the same problem on linux as on windows. "Export" controls not only the symbol visibility across shared library boundaries but also the module level visibility. E.g. this is a problem private void SomeImplementationDetail() { ... } void SomeTemplateFunc(T)() { SomeImplementationDetail(); } If you compile this into a shared library and all symbols are hidden by default unless marked with export it will fail to compile if someone tries to use it. Because the instanciated template SomeTemplateFunc will call the SomeImplementationDetail function which is not visible across the shared library boundary. To fix this you would have to do: export void SomeImplementationDetail() { ... } void SomeTemplateFunc(T)() { SomeImplementationDetail(); } But this means that users of the shared library would suddenly be allowed to call SomeImplementationDetail. The fix would be to make export an attribute instead of an protection level resulting in: private export void SomeImplementationDetail() { ... } void SomeTemplateFunc(T)() { SomeImplementationDetail(); }
Aug 23 2015
prev sibling parent "Dicebot" <public dicebot.lv> writes:
On Saturday, 22 August 2015 at 20:14:59 UTC, Walter Bright wrote:
 Marking them all as export will be inconvenient but is 
 possible - but I'd like
 to get something useful in return, like well-defined and 
 working export for
 example.
I'm not sure how export would help on Linux.
I have always been in support of actually enforcing export on Linux (== making all non-export symbols hidden). It is a key for heavy cross-module optimization.
Aug 23 2015
prev sibling next sibling parent "Freddy" <Hexagonalstar64 gmail.com> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the 
 program. To make it work, though, every class in the program 
 has to have a TypeInfo generated for it. This leads to bloat:
 What do you think?
Can't we just make that Object.factory() an empty template and lazily instantiate class TypeInfo when needed.
Aug 21 2015
prev sibling next sibling parent "Kagamin" <spam here.lot> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 What do you think?
Isn't typeinfo referenced from vtbl? So as long as the class is used, its typeinfo stays.
Aug 21 2015
prev sibling next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the 
 program. To make it work, though, every class in the program 
 has to have a TypeInfo generated for it. This leads to bloat:

   https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory 
 be able to instantiate classes marked as 'export'. This only 
 makes sense anyway.

 What do you think?
Just change Object.factory to require registration of the class. It isn't too much of an effort to designate the few classes where it's needed, really. It's even safer, because the class name could potentially come from user input, and needs to be sanitized anyway in this case.
Aug 21 2015
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/21/2015 4:44 AM, Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> wrote:
 Just change Object.factory to require registration of the class.
What mechanism do you propose for that?
Aug 21 2015
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Friday, 21 August 2015 at 21:37:34 UTC, Walter Bright wrote:
 On 8/21/2015 4:44 AM, Marc =?UTF-8?B?U2Now7x0eiI=?= 
 <schuetzm gmx.net> wrote:
 Just change Object.factory to require registration of the 
 class.
What mechanism do you propose for that?
http://forum.dlang.org/post/fxansmxbiobeshefszlm forum.dlang.org
Aug 21 2015
prev sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Friday, 21 August 2015 at 21:37:34 UTC, Walter Bright wrote:
 On 8/21/2015 4:44 AM, Marc =?UTF-8?B?U2Now7x0eiI=?= 
 <schuetzm gmx.net> wrote:
 Just change Object.factory to require registration of the 
 class.
What mechanism do you propose for that?
E.g.: template factoryConstructors(Args...) { // using void* because I don't know whether it's possible // to have a function pointer to a constructor void*[string] factoryConstructors; } void registerFactoryConstructor(Class, Args...)() if(is(Class == class)) { factoryConstructors!Args[Class.stringof] = ...; } Object factory(Args...)(string className, Args args) { auto constructor = factoryConstructors!Args[className]; return ...; } This even allows to call constructors with arguments. deadalnix's proposal is a nice way to automate this for an entire class hierarchy. Another possible mechanisms would be some UDA magic.
Aug 22 2015
parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Saturday, 22 August 2015 at 08:16:06 UTC, Marc Schütz wrote:
 Another possible mechanisms would be some UDA magic.
E.g.: class MyClass { factorizable this() { } factorizable this(string) { } this(int) { } } mixin registerFactoryConstructors; // for entire module
Aug 22 2015
prev sibling next sibling parent "Vladimir Panteleev" <thecybershadow.lists gmail.com> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the 
 program. To make it work, though, every class in the program 
 has to have a TypeInfo generated for it. This leads to bloat:

   https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory 
 be able to instantiate classes marked as 'export'. This only 
 makes sense anyway.

 What do you think?
An alternative which would be more work but wouldn't break code would be to put the "all the classes" structure in a separate section, which is only referenced by Object.factory. Thus, the structure will be GC-ed by the linker, unless Object.factory is actually used somewhere in the program. Not sure how this would tie in with shared objects though. Maybe this needs to be combined with your "export" idea.
Aug 21 2015
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 8/21/15 1:06 AM, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the program. To
 make it work, though, every class in the program has to have a TypeInfo
 generated for it. This leads to bloat:

    https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory be able to
 instantiate classes marked as 'export'. This only makes sense anyway.

 What do you think?
Knee-jerk reaction: sensible and meaningful, but we need to make a good case for breaking code. -- Andrei
Aug 21 2015
next sibling parent "tcak" <1ltkrs+3wyh1ow7kzn1k sharklasers.com> writes:
How expensive putting a flag for the compiler?

--exportall, -ea

to export all, otherwise, only the classes with "export" keyword 
are to be exported.
Aug 21 2015
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/21/2015 6:29 AM, Andrei Alexandrescu wrote:
 Knee-jerk reaction: sensible and meaningful, but we need to make a good case
for
 breaking code. -- Andrei
The case is: https://issues.dlang.org/show_bug.cgi?id=14758 i.e. D being unusable for embedded systems because of bloat. And it always has been a little strange to make every class available via Object.factory. I have a hard time imagining an application for it that needed more than a handful of classes available that way. The principle often used by languages (C, C++, Rust) is you only pay for what you use. With Object.factory, every program pays for it with every class, despite very few actual uses of it.
Aug 21 2015
next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Friday, 21 August 2015 at 20:26:29 UTC, Walter Bright wrote:
 On 8/21/2015 6:29 AM, Andrei Alexandrescu wrote:
 Knee-jerk reaction: sensible and meaningful, but we need to 
 make a good case for
 breaking code. -- Andrei
The case is: https://issues.dlang.org/show_bug.cgi?id=14758 i.e. D being unusable for embedded systems because of bloat. And it always has been a little strange to make every class available via Object.factory. I have a hard time imagining an application for it that needed more than a handful of classes available that way. The principle often used by languages (C, C++, Rust) is you only pay for what you use. With Object.factory, every program pays for it with every class, despite very few actual uses of it.
That sound reasonable and I advocated for changing Object.factory in the past for this very reason. That being said, if we are going to break code, we'd better be sure we do it for something that is worth it. That mean we need a way for user to repro the feature, and I rather avoid a dirty hack to do it, as proposed here. A generic solution, for instance, could be for a superclass to be able to mixin something in all its child. Such a feature can be used to make sure that all child have a mechanism to register themselves int he factory. Something à la class Base { super mixin { shared this() { library.register(typeid(typeof(this))); } } } class Child : Base { // The super mixin also gets expanded here. // But this does not have the same type. // Both end up being registered, whatever that means. } Such a solution can be leveraged by any library or user to do whatever they want. Sounds a better approach to me that introducing hacks.
Aug 21 2015
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/21/2015 2:59 PM, deadalnix wrote:
[...]
It's a good idea, but is still equivalent to manually annotating the classes one wishes to register, and still requires a new language feature.
Aug 21 2015
parent "deadalnix" <deadalnix gmail.com> writes:
On Friday, 21 August 2015 at 22:21:43 UTC, Walter Bright wrote:
 On 8/21/2015 2:59 PM, deadalnix wrote:
[...]
It's a good idea, but is still equivalent to manually annotating the classes one wishes to register, and still requires a new language feature.
Breaking the code must be worth it.
Aug 21 2015
prev sibling parent "rsw0x" <anonymous anonymous.com> writes:
On Friday, 21 August 2015 at 21:59:30 UTC, deadalnix wrote:
 Such a feature can be used to make sure that all child have a 
 mechanism to register themselves int he factory. Something à la

 class Base {
     super mixin {
         shared this() {
             library.register(typeid(typeof(this)));
         }
     }
 }

 class Child : Base {
     // The super mixin also gets expanded here.
     // But this does not have the same type.
     // Both end up being registered, whatever that means.
 }

 Such a solution can be leveraged by any library or user to do 
 whatever they want. Sounds a better approach to me that 
 introducing hacks.
+1, this seems like a great solution. now if only typeinfo could be completely redone...
Aug 21 2015
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2015-08-21 22:26, Walter Bright wrote:

 The principle often used by languages (C, C++, Rust) is you only pay for
 what you use. With Object.factory, every program pays for it with every
 class, despite very few actual uses of it.
A always thought of D as a bit more convenient language. Variables are automatically initialized, virtual by default, minimal reflation functionality, i.e. Object.factory. Although, all of these can be avoided except for Object.factory. -- /Jacob Carlborg
Aug 23 2015
prev sibling next sibling parent reply "ponce" <contact gam3sfrommars.fr> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:

 What do you think?
Do function pointer types also have TypeInfo? Derelict libraries has hundreds of them and my belief is that they are related. There were complaints about bloat at times. Those function pointer types typically don't need anything that TypeInfo provides.
Aug 21 2015
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/21/2015 2:53 PM, ponce wrote:
 Do function pointer types also have TypeInfo? Derelict libraries has hundreds
of
 them and my belief is that they are related.
Compile with -map and check to see what winds up in the binary.
Aug 21 2015
prev sibling next sibling parent "bitwise" <bitwise.pvt gmail.com> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the 
 program. To make it work, though, every class in the program 
 has to have a TypeInfo generated for it. This leads to bloat:

   https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory 
 be able to instantiate classes marked as 'export'. This only 
 makes sense anyway.

 What do you think?
Can't this be optional? -slim-rtti // hold the gravy -verbose-rtti // more gravy!
 On Friday, 21 August 2015 at 20:26:29 UTC, Walter Bright wrote:
[...]
 The principle often used by languages (C, C++, Rust) is you 
 only pay for what you use. With Object.factory, every program 
 pays for it with every class, despite very few actual uses of 
 it.
Object.factory() would probably get more use if D provided a full solution in this category. OffsetTypeInfo was never implemented, but is still collecting dust: https://github.com/D-Programming-Language/druntime/blob/master/src/object.d#L197 I would love to see OffsetTypeInfo implemented, and have the field name included as well so it could be used for serialization. I don't believe there has to be a "one size fits all" solution for this. Some people need small binaries, some need utility. Bit
Aug 21 2015
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 What do you think?
Well, one suggestion would be to simply version Object.factory so that programs that don't need it and don't want the bloat can define a version which versions it out. The it won't pull in all of the TypeInfos, and you won't get that bloat. It's not exactly an ideal solution, but it's easy enough to do that it might be worth it to get rid of that bloat for the folks who can't afford it. I do agree though that we should try and find a better way to fix the problem so that the situation is improved for everyone. - Jonathan M Davis
Aug 21 2015
prev sibling next sibling parent reply "Martin Nowak" <code dawg.eu> writes:
On Friday, 21 August 2015 at 05:06:47 UTC, Walter Bright wrote:
 The solution seems straightforward - only have Object.factory 
 be able to instantiate classes marked as 'export'. This only 
 makes sense anyway.
The export seems to be an arbitrary rule (and export is really broken currently). Let's just use every class that is linked into the binary (e.g. weakly referencing them), then it'll naturally work with all linker functionalities. This doesn't only affect Object.factory but also ModuleInfo.localClasses. I'd suggest we first add a new internal array of weakly linked classes, turn localClasses into an opApply function or range so it automatically skips null classes (weakly undefined), then change Object.factory to only load weakly linked classes. For an intermediate time we can keep the old array and print a deprecation warning in Object.factory when a class would no longer be available. https://github.com/D-Programming-Language/dmd/pull/4638
Aug 22 2015
parent reply "Benjamin Thaut" <code benjamin-thaut.de> writes:
On Saturday, 22 August 2015 at 09:44:48 UTC, Martin Nowak wrote:
 The export seems to be an arbitrary rule (and export is really 
 broken currently).
 Let's just use every class that is linked into the binary (e.g. 
 weakly referencing them), then it'll naturally work with all 
 linker functionalities.

 This doesn't only affect Object.factory but also 
 ModuleInfo.localClasses.
 I'd suggest we first add a new internal array of weakly linked 
 classes, turn localClasses into an opApply function or range so 
 it automatically skips null classes (weakly undefined), then 
 change Object.factory to only load weakly linked classes.

 For an intermediate time we can keep the old array and print a 
 deprecation warning in Object.factory when a class would no 
 longer be available.
 https://github.com/D-Programming-Language/dmd/pull/4638
How do you implement weak linking? It would be really usefull for my DLL work as well, but I couldn't find any way to make it work with the microsoft linker.
Aug 23 2015
parent Walter Bright <newshound2 digitalmars.com> writes:
On 8/23/2015 6:17 AM, Benjamin Thaut wrote:
 How do you implement weak linking? It would be really usefull for my DLL work
as
 well, but I couldn't find any way to make it work with the microsoft linker.
I've always had trouble with linker bugs when using weak linking, to the point where I simply gave up on using it.
Aug 23 2015
prev sibling next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 21 August 2015 at 15:06, Walter Bright via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 This function:



 enables a program to instantiate any class defined in the program. To make
 it work, though, every class in the program has to have a TypeInfo generated
 for it. This leads to bloat:

   https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory be able to
 instantiate classes marked as 'export'. This only makes sense anyway.

 What do you think?
I don't follow the reasoning, but yes! Kill it with fire! I'd rather see a compile option or something to disable it completely, like how disabling RTTI is a common C++ option.
Aug 22 2015
parent "rsw0x" <anonymous anonymous.com> writes:
On Saturday, 22 August 2015 at 23:33:15 UTC, Manu wrote:
 On 21 August 2015 at 15:06, Walter Bright via Digitalmars-d 
 <digitalmars-d puremagic.com> wrote:
 [...]
I don't follow the reasoning, but yes! Kill it with fire! I'd rather see a compile option or something to disable it completely, like how disabling RTTI is a common C++ option.
rtti is used heavily in the runtime hooks, this needs to be fixed first as far as I know.
Aug 22 2015
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2015-08-21 07:06, Walter Bright wrote:
 This function:



 enables a program to instantiate any class defined in the program. To
 make it work, though, every class in the program has to have a TypeInfo
 generated for it. This leads to bloat:

    https://issues.dlang.org/show_bug.cgi?id=14758

 and sometimes the bloat can be overwhelming.

 The solution seems straightforward - only have Object.factory be able to
 instantiate classes marked as 'export'. This only makes sense anyway.
If we're actually going to talk about solution then it seems better to have a flag that disables Object.factory. It won't break any code and everyone that doesn't like can disable it. Everybody wins. -- /Jacob Carlborg
Aug 23 2015
parent reply "w0rp" <devw0rp gmail.com> writes:
I think this is another case where Walter has got it right, by 
and large. I think we should try and use 'export' to cut down on 
binary bloat, and it looks like an acceptable solution.

I have said many times, lock your versions down, and don't update 
your D compiler until you're ready to pay the cost of updating. 
There is always a cost involved, small or great.
Aug 25 2015
parent reply Jacob Carlborg <doob me.com> writes:
On 2015-08-25 10:18, w0rp wrote:
 I think this is another case where Walter has got it right, by and
 large. I think we should try and use 'export' to cut down on binary
 bloat, and it looks like an acceptable solution.

 I have said many times, lock your versions down, and don't update your D
 compiler until you're ready to pay the cost of updating. There is always
 a cost involved, small or great.
I'm been doing that and I get a lot of complains from developers how want to use my libraries with later versions of the compiler. -- /Jacob Carlborg
Aug 25 2015
parent Daniel =?UTF-8?B?S296w6Fr?= via Digitalmars-d writes:
V Tue, 25 Aug 2015 10:34:57 +0200
Jacob Carlborg via Digitalmars-d <digitalmars-d puremagic.com> napsáno:

 On 2015-08-25 10:18, w0rp wrote:
 I think this is another case where Walter has got it right, by and
 large. I think we should try and use 'export' to cut down on binary
 bloat, and it looks like an acceptable solution.

 I have said many times, lock your versions down, and don't update
 your D compiler until you're ready to pay the cost of updating.
 There is always a cost involved, small or great.
I'm been doing that and I get a lot of complains from developers how want to use my libraries with later versions of the compiler.
As a library author (ideal case) you need to support both, some stable branch and some development branch ;-).
Aug 25 2015