Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
Merge pull request #254 from dawgfoto/ModuleGroup
Browse files Browse the repository at this point in the history
ModuleGroup
  • Loading branch information
andralex committed Jul 8, 2012
2 parents 1d7e41f + 59aaf67 commit 9706a92
Showing 1 changed file with 91 additions and 56 deletions.
147 changes: 91 additions & 56 deletions src/rt/minfo.d
Expand Up @@ -35,18 +35,56 @@ enum
MInew = 0x80000000 // it's the "new" layout
}

// Windows: this gets initialized by minit.asm
// Posix: this gets initialized in rt_moduleCtor()
extern (C) __gshared ModuleInfo*[] _moduleinfo_array;
extern(C) void _minit();

struct SortedCtors
struct ModuleGroup
{
void alloc(size_t n)
this(ModuleInfo*[] modules)
{
_modules = modules;
}

@property inout(ModuleInfo*)[] modules() inout
{
return _modules;
}

void sortCtors()
{
// don't bother to initialize, as they are getting overwritten anyhow
immutable n = _modules.length;
_ctors = (cast(ModuleInfo**).malloc(n * size_t.sizeof))[0 .. n];
_tlsctors = (cast(ModuleInfo**).malloc(n * size_t.sizeof))[0 .. n];
.sortCtors(this);
}

void runCtors()
{
// run independent ctors
runModuleFuncs!(m => m.ictor)(_modules);
// sorted module ctors
runModuleFuncs!(m => m.ctor)(_ctors);
// flag all modules as initialized
foreach (m; _modules)
m.flags = m.flags | MIctordone;
}

void runTlsCtors()
{
runModuleFuncs!(m => m.tlsctor)(_tlsctors);
}

void runTlsDtors()
{
runModuleFuncsRev!(m => m.tlsdtor)(_tlsctors);
}

void runDtors()
{
runModuleFuncsRev!(m => m.dtor)(_ctors);
// clean all initialized flags
foreach (m; _modules)
m.flags = m.flags & ~MIctordone;

free();
}

void free()
Expand All @@ -55,13 +93,24 @@ struct SortedCtors
_ctors = null;
.free(_tlsctors.ptr);
_tlsctors = null;
_modules = null;
}

ModuleInfo*[] _ctors;
private:
ModuleInfo*[] _modules;
ModuleInfo*[] _ctors;
ModuleInfo*[] _tlsctors;
}

__gshared SortedCtors _sortedCtors;
version (Windows)
{
// Windows: this gets initialized by minit.asm
// Posix: this gets initialized in _moduleCtor()
extern(C) __gshared ModuleInfo*[] _moduleinfo_array;
extern(C) void _minit();
}

__gshared ModuleGroup _moduleGroup;

/********************************************
* Iterate over all module infos.
Expand All @@ -71,7 +120,7 @@ int moduleinfos_apply(scope int delegate(ref ModuleInfo*) dg)
{
int ret = 0;

foreach (m; _moduleinfo_array)
foreach (m; _moduleGroup._modules)
{
// TODO: Should null ModuleInfo be allowed?
if (m !is null)
Expand All @@ -90,40 +139,27 @@ int moduleinfos_apply(scope int delegate(ref ModuleInfo*) dg)

extern (C) void rt_moduleCtor()
{
_moduleinfo_array = getModuleInfos();
_sortedCtors = sortCtors(_moduleinfo_array);

// run independent ctors
runModuleFuncs!((a) { return a.ictor; })(_moduleinfo_array);
// sorted module ctors
runModuleFuncs!((a) { return a.ctor; })(_sortedCtors._ctors);
// flag all modules as initialized
foreach (m; _moduleinfo_array)
m.flags = m.flags | MIctordone;
_moduleGroup = ModuleGroup(getModuleInfos());
_moduleGroup.sortCtors();
_moduleGroup.runCtors();
}

extern (C) void rt_moduleTlsCtor()
{
runModuleFuncs!((a) { return a.tlsctor; })(_sortedCtors._tlsctors);
_moduleGroup.runTlsCtors();
}

extern (C) void rt_moduleTlsDtor()
{
runModuleFuncsRev!((a) { return a.tlsdtor; })(_sortedCtors._tlsctors);
_moduleGroup.runTlsDtors();
}

extern (C) void rt_moduleDtor()
{
runModuleFuncsRev!((a) { return a.dtor; })(_sortedCtors._ctors);

// clean all initialized flags
foreach (m; _moduleinfo_array)
m.flags = m.flags & ~MIctordone;

_sortedCtors.free();
_moduleGroup.runDtors();
version (Posix)
.free(_moduleinfo_array.ptr);
_moduleinfo_array = null;
.free(_moduleGroup._modules.ptr);
_moduleGroup.free();
}

/********************************************
Expand Down Expand Up @@ -224,29 +260,35 @@ void runModuleFuncsRev(alias getfp)(ModuleInfo*[] modules)
* constructors.
*/

SortedCtors sortCtors(ModuleInfo*[] modules)
void sortCtors(ref ModuleGroup mgroup)
in
{
assert(mgroup._modules.length == mgroup._ctors.length);
assert(mgroup._modules.length == mgroup._tlsctors.length);
}
body
{
enum AllocaLimit = 100 * 1024; // 100KB

immutable size = modules.length * StackRec.sizeof;
immutable len = mgroup._modules.length;
immutable size = len * StackRec.sizeof;

if (!size)
if (!len)
{
return SortedCtors.init;
return;
}
else if (size <= AllocaLimit)
{
auto p = cast(ubyte*).alloca(size);
p[0 .. size] = 0;
return sortCtorsImpl(modules, (cast(StackRec*)p)[0 .. modules.length]);
sortCtorsImpl(mgroup, (cast(StackRec*)p)[0 .. len]);
}
else
{
auto p = cast(ubyte*).malloc(size);
p[0 .. size] = 0;
auto result = sortCtorsImpl(modules, (cast(StackRec*)p)[0 .. modules.length]);
sortCtorsImpl(mgroup, (cast(StackRec*)p)[0 .. len]);
.free(p);
return result;
}
}

Expand Down Expand Up @@ -297,21 +339,18 @@ void onCycleError(StackRec[] stack)
throw new Exception("Aborting!");
}

private SortedCtors sortCtorsImpl(ModuleInfo*[] modules, StackRec[] stack)
private void sortCtorsImpl(ref ModuleGroup mgroup, StackRec[] stack)
{
SortedCtors result;
result.alloc(modules.length);

size_t stackidx;
bool tlsPass;

Lagain:

const mask = tlsPass ? (MItlsctor | MItlsdtor) : (MIctor | MIdtor);
auto ctors = tlsPass ? result._tlsctors : result._ctors;
auto ctors = tlsPass ? mgroup._tlsctors : mgroup._ctors;
size_t cidx;

ModuleInfo*[] mods = modules;
ModuleInfo*[] mods = mgroup._modules;
size_t idx;
while (true)
{
Expand Down Expand Up @@ -375,7 +414,7 @@ private SortedCtors sortCtorsImpl(ModuleInfo*[] modules, StackRec[] stack)
/* Internal runtime error, dependency on an uninitialized
* module outside of the current module group.
*/
(stackidx < modules.length) || assert(0);
(stackidx < mgroup._modules.length) || assert(0);

// recurse
stack[stackidx++] = StackRec(mods, idx);
Expand All @@ -400,22 +439,18 @@ private SortedCtors sortCtorsImpl(ModuleInfo*[] modules, StackRec[] stack)
break;
}
// store final number
tlsPass ? result._tlsctors : result._ctors = ctors[0 .. cidx];
tlsPass ? mgroup._tlsctors : mgroup._ctors = ctors[0 .. cidx];

// clean flags
for (size_t i = 0; i < modules.length; ++i)
{ auto m = modules[i];
foreach(m; mgroup._modules)
m.flags = m.flags & ~(MIctorstart | MIctordone);
}

// rerun for TLS constructors
if (!tlsPass)
{
tlsPass = true;
goto Lagain;
}

return result;
}

version (unittest)
Expand Down Expand Up @@ -470,12 +505,12 @@ unittest

void checkExp(ModuleInfo*[] dtors=null, ModuleInfo*[] tlsdtors=null)
{
auto ptrs = [&m0, &m1, &m2];
auto sorted = sortCtors(ptrs);
foreach (m; ptrs)
auto mgroup = ModuleGroup([&m0, &m1, &m2]);
mgroup.sortCtors();
foreach (m; mgroup._modules)
assert(!(m.flags & (MIctorstart | MIctordone)));
assert(sorted._ctors == dtors);
assert(sorted._tlsctors == tlsdtors);
assert(mgroup._ctors == dtors);
assert(mgroup._tlsctors == tlsdtors);
}

// no ctors
Expand Down

0 comments on commit 9706a92

Please sign in to comment.