On 12/21/11 17:42, Kagamin wrote:
>> Could you elaborate?
>
> As I remember, these features rely heavily on linker support, namely on how
> it merges sections. Each pointer to static ctor (and unittest) is placed in a
> section, then these sections are merged by linker and you get an array of
> pointers to all static ctors and unittests. The startup code reads the
> pointers in sequence and executes them. If some section is removed, the
> corresponding static ctor won't be run.
>
>> Real code, that i was testing with previously, contained static module ctors
>> which
>> worked, and i just tried a simple two module test w/ multiple
>> shared_[cd]tors +
>> static_[cd]tors + unittests -- all of them are called as expected.
>
> If so then ok.
I suspected that was what you were worried about and did that test [1],
which gives the expected output. But looking now at the list of linker
gc'ed sections, i notice ld does claim to have removed eg
".text._D11gcfuncdata218_sharedStaticCtor3FZv", which is one of the ctors.
The reason things still work is because the code is also inlined in
"_D11gcfuncdata215__modsharedctorFZv" together with the other ctor.
Aha, the compiler (gdc) actually inlined all the [cd]tors when run at -O3,
and the "real" constructor was then garbage collected by the linker. Phew.
Compiling with -O2 makes modsharedctor call all the ctors instead, and they
are then not gc'ed.
Why the compiler emits the unused outofline ctors is another question.
Maybe i should start marking them as private?...
Turned out not to be a good idea, as the compiler silently accepts
"shared private static this() {...}" and does not emit the dead code anymore.
But.. this constructor is run together with the un-shared ones, ie possibly
_after_ them... (this is not section-gc specific, happens w/o it too)
artur
[1]
import std.stdio;
/* gcfuncdata2.d is a copy of this module, w/o main() */
import gcfuncdata2;
auto p(S...)(S args) { return stdout.writeln(__FILE__~": ", args); }
void main(string[] args){ p("main"); }
static this() { p("ctor1"); }
static this() { p("ctor2"); }
shared static this() { p("shared ctor1"); }
shared static this() { p("shared ctor2"); }
static ~this() { p("dtor1"); }
static ~this() { p("dtor2"); }
shared static ~this() { p("shared dtor1"); }
shared static ~this() { p("shared dtor2"); }
unittest { p("unittest1"); }
unittest { p("unittest2"); }